mysql資料庫SQL最佳化2
SQL最佳化2
測試樣例wget />
ICP: 5.6 Index Condition Pushdown(ICP)
應用場景:where條件中其中幾個欄位,在聯合索引的範圍內;
explain select * from rental where rental_date='2006-02-14 15:16:03' and customer_id>=300 and customer_id<=400\G
mysql> show index from rental;
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| rental | 0 | PRIMARY | 1 | rental_id | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 1 | rental_date | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 2 | inventory_id | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 3 | customer_id | A | 16298 | NULL | NULL | | BTREE | |
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
查詢改寫
mysql> explain select * from actor where last_name like '%NI%';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 200 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
mysql> explain select * from (select actor_id from actor where last_name like '%NI%') a,actor b where a.actor_id=b.actor_id;
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | PRIMARY | b | eq_ref | PRIMARY | PRIMARY | 2 | a.actor_id | 1 | |
| 2 | DERIVED | actor | index | NULL | idx_actor_last_name | 137 | NULL | 200 | Using where; Using index |
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
注:innodb表上的二級索引實際上儲存索引欄位和主鍵欄位;
mysql> explain select * from customer where customer_id not in (select customer_id from payment);
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
| 1 | PRIMARY | customer | ALL | NULL | NULL | NULL | NULL | 541 | Using where |
| 2 | DEPENDENT SUBQUERY | payment | index_subquery | idx_fk_customer_id | idx_fk_customer_id | 2 | func | 12 | Using index |
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
2 rows in set (0.00 sec)
mysql> explain select * from customer a left join payment b on a.customer_id=b.customer_id where b.customer_id is null;
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 541 | |
| 1 | SIMPLE | b | ref | idx_fk_customer_id | idx_fk_customer_id | 2 | sakila.a.customer_id | 12 | Using where; Not exists |
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
2 rows in set (0.00 sec)
mysql5.5以下版本(包括5.5)子查詢不如關聯查詢(join)
mysql> explain select film_id,description from film order by title limit 50,5;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | film | ALL | NULL | NULL | NULL | NULL | 1028 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
mysql> explain select a.film_id,a.description from film a inner join (select film_id from film order by title limit 50,5)b on a.film_id=b.film_id;
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 55 | NULL |
| 1 | PRIMARY | a | eq_ref | PRIMARY | PRIMARY | 2 | b.film_id | 1 | NULL |
| 2 | DERIVED | film | index | NULL | idx_title | 767 | NULL | 1028 | Using index |
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
注:資料型別出現隱式轉換的時候也不會使用索引
檢視索引使用情況
mysql> show status like 'Handler_read_key';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Handler_read_key | 13 |
+------------------+-------+
如果索引正在工作,Handler_read_key的值將很高,這個值代表了一個行被索引值讀的次數,很低的值表明增加索引得到的效能改善不高;
mysql> show status like 'Handler_read_rnd_next';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_rnd_next | 1323 |
+-----------------------+-------+
Handler_read_rnd_next的含義是在資料檔案中讀下一行的請求數,如果正進行大量表掃描,該值會很高;
定期分析、檢查、最佳化
analyze(myisam 相當於myisamchk -a,innodb)本語句用於分析和儲存表的關鍵字分佈,分析的結果將可以使得系統得到準確的統計資訊,使得sql能夠生成正確的執行計劃;
check(myisam,innodb) 檢查表的作用是檢查一個或多個表是否有錯誤;
optimize(myisam,innodb) 整理表空間碎片
alter table payment engine=innodb; 收回多餘的表空間
注意:以上四種操作對錶鎖定,資料不繁忙的時候操作;
批次插入資料
myisam
alter table tab_name disable keys;(非唯一索引)(差6倍)
load data
alter table tab_name enable keys;
bulk_insert_buffer_size
innodb
1.按主鍵順序插入(1倍)
2.set unique_checks=0
3.set autocommit=0
all
多行插入
不進記憶體
load=20insert
排序
max_length_for_sort_data
sort_buffer_size
group by
預設情況下,mysql對所有group by是有排序的如下圖,如果想避免排序可以order by null
mysql> explain select payment_date,sum(amount) from payment group by payment_date;
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| 1 | SIMPLE | payment | index | NULL | idx_payment_date | 15 | NULL | 15123 | Using index |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
mysql> explain select payment_date,sum(amount) from payment group by payment_date order by payment_date;
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| 1 | SIMPLE | payment | index | NULL | idx_payment_date | 15 | NULL | 15123 | Using index |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
測試樣例wget />
ICP: 5.6 Index Condition Pushdown(ICP)
應用場景:where條件中其中幾個欄位,在聯合索引的範圍內;
explain select * from rental where rental_date='2006-02-14 15:16:03' and customer_id>=300 and customer_id<=400\G
mysql> show index from rental;
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| rental | 0 | PRIMARY | 1 | rental_id | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 1 | rental_date | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 2 | inventory_id | A | 16298 | NULL | NULL | | BTREE | |
| rental | 1 | idx_rental_date | 3 | customer_id | A | 16298 | NULL | NULL | | BTREE | |
+--------+------------+---------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
查詢改寫
mysql> explain select * from actor where last_name like '%NI%';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 200 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
mysql> explain select * from (select actor_id from actor where last_name like '%NI%') a,actor b where a.actor_id=b.actor_id;
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | PRIMARY | b | eq_ref | PRIMARY | PRIMARY | 2 | a.actor_id | 1 | |
| 2 | DERIVED | actor | index | NULL | idx_actor_last_name | 137 | NULL | 200 | Using where; Using index |
+----+-------------+------------+--------+---------------+---------------------+---------+------------+------+--------------------------+
注:innodb表上的二級索引實際上儲存索引欄位和主鍵欄位;
mysql> explain select * from customer where customer_id not in (select customer_id from payment);
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
| 1 | PRIMARY | customer | ALL | NULL | NULL | NULL | NULL | 541 | Using where |
| 2 | DEPENDENT SUBQUERY | payment | index_subquery | idx_fk_customer_id | idx_fk_customer_id | 2 | func | 12 | Using index |
+----+--------------------+----------+----------------+--------------------+--------------------+---------+------+------+-------------+
2 rows in set (0.00 sec)
mysql> explain select * from customer a left join payment b on a.customer_id=b.customer_id where b.customer_id is null;
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 541 | |
| 1 | SIMPLE | b | ref | idx_fk_customer_id | idx_fk_customer_id | 2 | sakila.a.customer_id | 12 | Using where; Not exists |
+----+-------------+-------+------+--------------------+--------------------+---------+----------------------+------+-------------------------+
2 rows in set (0.00 sec)
mysql5.5以下版本(包括5.5)子查詢不如關聯查詢(join)
mysql> explain select film_id,description from film order by title limit 50,5;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | film | ALL | NULL | NULL | NULL | NULL | 1028 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
mysql> explain select a.film_id,a.description from film a inner join (select film_id from film order by title limit 50,5)b on a.film_id=b.film_id;
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 55 | NULL |
| 1 | PRIMARY | a | eq_ref | PRIMARY | PRIMARY | 2 | b.film_id | 1 | NULL |
| 2 | DERIVED | film | index | NULL | idx_title | 767 | NULL | 1028 | Using index |
+----+-------------+------------+--------+---------------+-----------+---------+-----------+------+-------------+
注:資料型別出現隱式轉換的時候也不會使用索引
檢視索引使用情況
mysql> show status like 'Handler_read_key';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| Handler_read_key | 13 |
+------------------+-------+
如果索引正在工作,Handler_read_key的值將很高,這個值代表了一個行被索引值讀的次數,很低的值表明增加索引得到的效能改善不高;
mysql> show status like 'Handler_read_rnd_next';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| Handler_read_rnd_next | 1323 |
+-----------------------+-------+
Handler_read_rnd_next的含義是在資料檔案中讀下一行的請求數,如果正進行大量表掃描,該值會很高;
定期分析、檢查、最佳化
analyze(myisam 相當於myisamchk -a,innodb)本語句用於分析和儲存表的關鍵字分佈,分析的結果將可以使得系統得到準確的統計資訊,使得sql能夠生成正確的執行計劃;
check(myisam,innodb) 檢查表的作用是檢查一個或多個表是否有錯誤;
optimize(myisam,innodb) 整理表空間碎片
alter table payment engine=innodb; 收回多餘的表空間
注意:以上四種操作對錶鎖定,資料不繁忙的時候操作;
批次插入資料
myisam
alter table tab_name disable keys;(非唯一索引)(差6倍)
load data
alter table tab_name enable keys;
bulk_insert_buffer_size
innodb
1.按主鍵順序插入(1倍)
2.set unique_checks=0
3.set autocommit=0
all
多行插入
不進記憶體
load=20insert
排序
max_length_for_sort_data
sort_buffer_size
group by
預設情況下,mysql對所有group by是有排序的如下圖,如果想避免排序可以order by null
mysql> explain select payment_date,sum(amount) from payment group by payment_date;
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| 1 | SIMPLE | payment | index | NULL | idx_payment_date | 15 | NULL | 15123 | Using index |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
mysql> explain select payment_date,sum(amount) from payment group by payment_date order by payment_date;
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
| 1 | SIMPLE | payment | index | NULL | idx_payment_date | 15 | NULL | 15123 | Using index |
+----+-------------+---------+-------+---------------+------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29620572/viewspace-1809391/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql資料庫SQL最佳化MySql資料庫
- mysql資料庫SQL最佳化3MySql資料庫
- 【MySQL】資料庫最佳化MySql資料庫
- mysql資料庫最佳化MySql資料庫
- MySQL資料庫效能最佳化MySql資料庫
- mysql資料庫最佳化彙總MySql資料庫
- 資料庫最佳化技巧 - SQL語句最佳化資料庫SQL
- MYSQL資料庫------SQL優化MySql資料庫優化
- PG資料庫SQL最佳化小技巧資料庫SQL
- 【資料庫學習】資料庫平臺:mysql,sql server資料庫MySqlServer
- 在SQL Server資料庫中匯入MySQL資料庫Server資料庫MySql
- MySQL 資料庫與 SQL 優化MySql資料庫優化
- SQL Server 資料庫 最佳化 效能瓶頸SQLServer資料庫
- SQL 資料庫學習 Part 2SQL資料庫
- MySQL資料庫高併發最佳化配置MySql資料庫
- 資料庫查詢和資料庫(MySQL)索引的最佳化建議資料庫MySql索引
- MySQL資料庫binlog解析神器-binlog2sql應用MySql資料庫
- Django 2連線MySQL資料庫DjangoMySql資料庫
- Mysql資料庫大表最佳化方案和Mysql大表最佳化步驟MySql資料庫
- 1.4 資料庫和常用SQL語句(正文)——MySQL資料庫命令和SQL語句資料庫MySql
- mysql資料庫最佳化需要遵守的原則MySql資料庫
- MySQL/Oracle資料庫最佳化總結(非常全面)MySqlOracle資料庫
- MySQL資料庫最佳化實踐--硬體方面MySql資料庫
- 分散式 SQL 資料庫與表格最佳化技術分散式SQL資料庫
- 50種方法最佳化SQL Server資料庫查詢SQLServer資料庫
- sql最佳化(mysql)MySql
- 用SQL命令檢視Mysql資料庫大小MySql資料庫
- SQL、Mysql、資料庫到底什麼關係MySql資料庫
- oracle資料庫巡檢最佳化-使用sql語句快速定位資料庫瓶頸Oracle資料庫SQL
- 2.資料庫Mysql--------基本操作資料庫MySql
- SQL2K資料庫開發四之刪除資料庫SQL資料庫
- MySQL 資料庫最佳化的具體方法說明MySql資料庫
- MySql資料庫最佳化的幾條核心建議MySql資料庫
- 從運維角度淺談MySQL資料庫最佳化運維MySql資料庫
- 談談資料從sql server資料庫匯入mysql資料庫的體驗(轉)Server資料庫MySql
- mysql資料庫sql語句基礎知識MySql資料庫
- MySQL資料庫:7、SQL常用查詢語句MySql資料庫
- SQL資料庫管理工具:SQLPro for MySQL for Mac資料庫MySqlMac