2017-04-17 118 views
0

我有兩個表CUSTOMER_ORDER_PUBLIC和LINEITEM_PUBLIC它有以下指標:查詢優化器不使用索引

+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table     | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| CUSTOMER_ORDER_PUBLIC |   1 | O_ORDERKEY |   1 | O_ORDERKEY | A   |  2633457 |  NULL | NULL | YES | BTREE  |   |    | 
| CUSTOMER_ORDER_PUBLIC |   1 | O_ORDERDATE |   1 | O_ORDERDATE | A   |  2350 |  NULL | NULL | YES | BTREE  |   |    | 
| CUSTOMER_ORDER_PUBLIC |   1 | PUB_C_CUSTKEY |   1 | PUB_C_CUSTKEY | A   |  273000 |  NULL | NULL |  | BTREE  |   |    | 
+-----------------------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

和:

+-----------------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table   | Non_unique | Key_name    | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+-----------------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| LINEITEM_PUBLIC |   0 | PRIMARY    |   1 | PUB_L_ORDERKEY | A   | 16488602 |  NULL | NULL |  | BTREE  |   |    | 
| LINEITEM_PUBLIC |   0 | PRIMARY    |   2 | PUB_L_LINENUMBER | A   | 44146904 |  NULL | NULL |  | BTREE  |   |    | 
| LINEITEM_PUBLIC |   1 | LINEITEM_PRIVATE_FK2 |   1 | PUB_L_PARTKEY | A   |  2083757 |  NULL | NULL |  | BTREE  |   |    | 
| LINEITEM_PUBLIC |   1 | LINEITEM_PRIVATE_FK3 |   1 | PUB_L_SUPPKEY | A   |  85599 |  NULL | NULL |  | BTREE  |   |    | 
+-----------------+------------+----------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

每次我運行一個解釋一個特定的查詢,我得到的如下:

mysql> EXPLAIN SELECT * 
    FROM CUSTOMER_ORDER_PUBLIC 
    LEFT OUTER JOIN LINEITEM_PUBLIC ON O_ORDERKEY= PUB_L_ORDERKEY; 
+----+-------------+-----------------------+------------+------+---------------+---------+---------+---------------------------------------+---------+----------+-------+ 
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref         | rows | filtered | Extra | 
+----+-------------+-----------------------+------------+------+---------------+---------+---------+---------------------------------------+---------+----------+-------+ 
| 1 | SIMPLE  | CUSTOMER_ORDER_PUBLIC | NULL  | ALL | NULL   | NULL | NULL | NULL         | 2900769 | 100.00 | NULL | 
| 1 | SIMPLE  | LINEITEM_PUBLIC  | NULL  | ref | PRIMARY  | PRIMARY | 4  | TPCH.CUSTOMER_ORDER_PUBLIC.O_ORDERKEY |  2 | 100.00 | NULL | 
+----+-------------+-----------------------+------------+------+---------------+---------+---------+---------------------------------------+---------+----------+-------+ 

由於某種原因,查詢優化器沒有使用索引(O_ORDERK安永),即使我使用FORCE INDEX。我知道很多人發佈了類似的問題,但我嘗試了一切,似乎沒有任何幫助!

任何其他建議將不勝感激!

編輯: 使用的查詢如下:

SELECT * FROM CUSTOMER_ORDER_PUBLIC 
    LEFT OUTER JOIN LINEITEM_PUBLIC ON O_ORDERKEY= PUB_L_ORDERKEY; 
+1

你還可以包含查詢嗎?請注意,如果您將'CUSTOMER_ORDER_PUBLIC'加入'LINEITEM_PUBLIC',那麼即使在聯接中使用索引,也需要對前者進行全表掃描。 –

+0

@TimBiegeleisen SELECT * FROM CUSTOMER_ORDER_PUBLIC LEFT OUTER JOIN LINEITEM_PUBLIC ON O_ORDERKEY = PUB_L_ORDERKEY; – Maya

+1

@Maya:請*編輯*問題以包含其他信息;不要將其作爲對問題的評論。 – spencer7593

回答

2

對於此查詢:

SELECT * 
FROM CUSTOMER_ORDER_PUBLIC cop LEFT OUTER JOIN 
    LINEITEM_PUBLIC lp 
    ON cop.O_ORDERKEY = lp.PUB_L_ORDERKEY; 

對於此查詢,您想對LINEITEM_PUBLIC(PUB_L_ORDERKEY)的索引。當然,你已經有了這個索引,因爲這是主鍵中的第一個鍵。

沒有理由在CUSTOMER_ORDER_PUBLIC上使用索引,因爲表中的所有行都將轉到結果集。

+1

要添加到Gordon所說的內容,MySQL必須在加入+1 –

1

FORCE INDEX提示告訴優化器對錶的全面掃描非常昂貴。

觀察到的行爲的最可能的解釋是,優化器認爲它需要訪問表中的每一行,並且提示中建議的索引是而不是查詢的覆蓋索引。

基於EXPLAIN輸出,我們在JOIN操作中只能看到單個謂詞的證據。看起來優化器正在選擇CUSTOMER_ORDER_PUBLIC作爲連接的驅動表,並使用LINEITEM_PUBLIC表中的索引。

我不確定任何回答你問的問題。 (我不確定是否有人問到問題。)缺少實際的SQL語句,我們只是猜測。

我有一個問題:除了FORCE INDEX提示,爲什麼我們會期望優化器使用特定的索引?爲什麼這是一個合理的期望?

+0

謝謝@ spencer7593期間對「CUSTOMER_ORDER_PUBLIC」執行全表掃描!正如@Gordon Linoff指出的那樣,我認爲需要掃描整個表格,因爲它是左外連接。我完全錯過了那部分。謝謝你的回答! – Maya

+1

某些查詢可以通過全面掃描*覆蓋*索引來滿足,而不需要查找底層表中的數據頁面。例如'SELECT o.O_ORDERKEY,l。* FROM CUSTOMER_ORDER_PUBLIC o LEFT JOIN LINEITEM_PUBLIC l ON l.PUB_L_ORDERKEY = o.O_ORDERKEY'。在這種情況下,優化器*可以*使用'O_ORDERKEY'列上的索引 – spencer7593

+0

@Maya - 編號'LEFT OUTER JOIN'不會導致全表掃描。事實上你沒有過濾任何東西(通過'WHERE')意味着你想要全部表中的一個。 'LEFT'表示它是_left_表的所有內容,但是對於這些行中的每一行,請檢查_right_表! –