2017-06-17 45 views
0

這可能是以前被問過的,但是我還沒有找到具有特定問題的線程。所以我有一個索引很大的表格,裏面有超過2500萬行,速度非常重要。我一直在努力盡可能優化結果,但有些奇怪的事情仍在繼續。MySQL中嚴重索引的表,但錯誤的索引正在使用導致執行時間很長

我有這個表:

當在只有一列做查詢的WHERE子句,它的作品,因爲它應該,但是,當我做 EXPLAIN EXTENDED SELECT * FROM externallinks_global FORCE INDEX (APIINDEX1,APIINDEX2,APIINDEX3,APIINDEX4,APIINDEX5,APIINDEX6,APIINDEX7,APIINDEX8) LEFT JOIN externallinks_paywall ON externallinks_global.paywall_id=externallinks_paywall.paywall_id WHERE ( live_state IN (0, 7) OR externallinks_global.paywall_id IN (SELECT paywall_id FROM externallinks_paywall WHERE paywall_status IN (3))) AND審查= 0 LIMIT 100000,1001;

出於某種原因,它試圖使用REVIEWED索引而不是APIINDEX5。我試圖強制它使用它,但它決定不使用索引。我有點迷路。我顯然做錯了什麼,但我不知道是什麼。

下面是從上述查詢的解釋:

+------+--------------+-----------------------+--------+---------------------------------------------------+---------------+---------+--------------------------------------------------+----------+----------+-------------+ 
| id | select_type | table     | type | possible_keys          | key   | key_len | ref            | rows  | filtered | Extra  | 
+------+--------------+-----------------------+--------+---------------------------------------------------+---------------+---------+--------------------------------------------------+----------+----------+-------------+ 
| 1 | PRIMARY  | externallinks_global | ALL | APIINDEX3,APIINDEX4,APIINDEX6,APIINDEX2,APIINDEX5 | NULL   | NULL | NULL            | 27193330 | 100.00 | Using where | 
| 1 | PRIMARY  | externallinks_paywall | eq_ref | PRIMARY           | PRIMARY  | 4  | s51059__cyberbot.externallinks_global.paywall_id |  1 | 100.00 |    | 
| 2 | MATERIALIZED | externallinks_paywall | ref | PRIMARY,PAYWALLSTATUS        | PAYWALLSTATUS | 1  | const           |  768 | 100.00 | Using index | 
+------+--------------+-----------------------+--------+---------------------------------------------------+---------------+---------+--------------------------------------------------+----------+----------+-------------+ 
3 rows in set, 1 warning (0.00 sec) 

回答

1

的問題是在你的WHERE條款:

WHERE (live_state IN (0, 7) OR externallinks_global.paywall_id IN (SELECT paywall_id FROM externallinks_paywall WHEREpaywall_statusIN (3))) AND reviewed=0 


綜合指數的有:

INDEX `APIINDEX5` (`live_state` ASC, `paywall_id` ASC, `reviewed` ASC) 

可以用來做任何最左邊的前綴查詢(列的組合):

如果表具有多列索引,則優化器可以使用該索引的任何最左側前綴來查找行。

但你正在嘗試做的是live_stateORpaywall_id查詢,使它的live_state獨立和離開的Mysql無法使用索引的問題。

這裏是如何Mysql documentation說明它:

假設一個表有以下規格:

CREATE TABLE test (
    id   INT NOT NULL, 
    last_name CHAR(30) NOT NULL, 
    first_name CHAR(30) NOT NULL, 
    PRIMARY KEY (id), 
    INDEX name (last_name,first_name) 
); 

...

但是,名稱索引未使用用於查詢以下查詢:

SELECT * FROM test WHERE first_name='Michael'; 

SELECT * FROM test 
    WHERE last_name='Widenius' OR first_name='Michael'; 

你可能嘗試做克服分爲兩個部分分裂查詢, 合併UNION

第一部分將查詢方式:

live_state IN (0, 7) AND reviewed=0 

(應該使用INDEX APIINDEX6

和第二部分將通過查詢:

paywall_id IN (...) AND reviewed=0 

(使用INDEX PAYWALLID除非你加一個新的paywall_id +評論索引)。

+0

感謝您的及時迴應。我會試一試並報告。 – Cyberpower678

+0

感謝您的幫助。按照你的解釋工作。 – Cyberpower678

相關問題