2016-12-16 47 views
1

我試圖用EXPLAIN以提高通過索引上某些查詢的性能,我用SHOW index FROM TableB;每次rows柱的側向承載力在查詢的EXPLAIN輸出改變爲什麼在每個SHOW索引之後EXPLAIN的輸出會改變?

防爆我注意到:

mysql> EXPLAIN Select A.id 
    From TableA A 
    Inner join TableB B 
     On A.address = B.address And A.code = B.code 
    Group by A.id 
    Having count(distinct B.id) = 1; 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref         | rows | Extra          | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
| 1 | SIMPLE  | B  | index | test_index | PRIMARY | 518  | NULL         | 10561 | Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | A  | eq_ref | PRIMARY  | PRIMARY | 514  | db.B.address,db.B.code    |  1 |            | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
2 rows in set (0.00 sec) 

mysql> show index from TableB; 
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table  | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| TableB |   0 | PRIMARY  |   1 | id   | A   |   7 |  NULL | NULL |  | BTREE  |   | 
| TableB |   0 | PRIMARY  |   2 | address  | A   |   21 |  NULL | NULL |  | BTREE  |   | 
| TableB |   0 | PRIMARY  |   3 | code  | A   |  10402 |  NULL | NULL |  | BTREE  |   | 
| TableB |   1 | test_index |   1 | address  | A   |   1 |  NULL | NULL |  | BTREE  |   | 
| TableB |   1 | test_index |   2 | code  | A   |  10402 |  NULL | NULL |  | BTREE  |   | 
| TableB |   1 | test_index |   3 | id   | A   |  10402 |  NULL | NULL |  | BTREE  |   | 
+-----------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
6 rows in set (0.03 sec) 

和...

mysql> EXPLAIN Select A.id 
     From TableA A 
     Inner join TableB B 
      On A.address = B.address And A.code = B.code Group by A.id 
     Having count(distinct B.id) = 1; 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref         | rows | Extra          | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
| 1 | SIMPLE  | B  | index | test_index | PRIMARY | 518  | NULL         | 9800 | Using index; Using temporary; Using filesort | 
| 1 | SIMPLE  | A  | eq_ref | PRIMARY  | PRIMARY | 514  | db.B.address,db.B.code    |  1 |            | 
+----+-------------+-------+--------+---------------+---------+---------+---------------------------------------+-------+----------------------------------------------+ 
2 rows in set (0.00 sec) 

這是爲什麼發生?

+0

當「持久統計信息」變爲可用時,聽起來您使用的版本早於5.6.6。 –

回答

3

rows列應僅作爲粗略估計。這不是一個確切的數字。

它基於統計估計在查詢過程中將檢查多少行。只有在實際執行查詢之後才能知道實際的行數。

統計數據基於定期從表中讀取的樣本。例如,在運行ANALYZE TABLE或某些INFORMATION_SCHEMA查詢或某些SHOW語句之後,偶爾會重新讀取這些樣本。

+0

「解釋擴展」對此有什麼影響? – Rahul

+0

否,EXPLAIN EXTENDED僅僅意味着將另一列信息添加到EXPLAIN輸出中,以顯示查詢過濾的行的估計百分比。這個選項在MySQL 5.7中是多餘的,因爲現在默認包含該列。 –

+0

太好了...謝謝你的迴應Bill。 – Rahul

0

我沒有發現統計數字有20%的變化是一個大問題。在很多情況下,想象一下圖像就像是一個上拋的拋物線,你需要知道你所處的最小點的哪一邊。在複雜查詢中,Optimizer可能會混淆,它需要的不僅僅是簡單的統計信息,例如MariaDB 10.0/10.1的Histograms。 (我沒有足夠的經驗來說明這是否取得了很大進展。)

無論統計數據如何,您的特定查詢可能只會以一種方式執行。一個複雜查詢的例子是JOINWHERE子句過濾每個表。優化器必須決定從哪個表開始。另一種情況是一個表格,其中有一個WHEREORDER BY,它們不能同時被一個索引處理 - 它是否應該使用索引進行過濾,但是必須進行排序?或者它應該使用ORDER BY的索引,但必須隨時過濾?

相關問題