2012-09-12 53 views
0

傢伙試圖總結我的頭周圍MySQL查詢爲什麼它掃描表中的所有行MySQL查詢掃描所有行

我有2個表topic_entry和topic_user

CREATE TABLE `topic_entry` (
    `entry_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `topic_id` bigint(20) unsigned NOT NULL, 
    `entry_created` datetime NOT NULL, 
    `entry_object` text, 
    `level` tinyint(4) NOT NULL DEFAULT '3', 
    PRIMARY KEY (`entry_id`), 
    KEY `entry_created` (`entry_created`), 
    KEY `level` (`level`), 
    KEY `topic_id_2` (`topic_id`,`entry_id`) 
) ENGINE=MyISAM; 

CREATE TABLE `topic_user` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `topic_id` bigint(20) unsigned NOT NULL, 
    `user_id` varchar(100) NOT NULL, 
    `private` enum('y','n') DEFAULT NULL, 
    `freq` enum('a','d','w') DEFAULT NULL, 
    `topic_id_freq` varchar(10) DEFAULT NULL, 
    `casematch` enum('0','1') DEFAULT '0', 
    `textmatch` enum('0','1') DEFAULT '0', 
    `topic_name_case` varchar(100) DEFAULT '', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `topic_id_user_id` (`topic_id`,`user_id`), 
    KEY `user_id` (`user_id`), 
    KEY `topic_id_freq` (`topic_id_freq`) 
) ENGINE=MyISAM; 

這是查詢我我試圖運行

explain 
select te.topic_id,te.entry_id 
from topic_entry te 
WHERE te.topic_id in (select topic_id 
         from topic_user where user_id ='xyz') 
    AND te.level=4 
    AND te.entry_id > 0 
ORDER BY te.entry_id DESC 
LIMIT 5; 

解釋輸出表明,它掃描所有的行

| 1 | PRIMARY| te | range | PRIMARY,level | PRIMARY | 8 | NULL| **722978** | Using where    | 
| 2 | DEPENDENT SUBQUERY | topic_user | unique_subquery | topic_id_user_id,user_id | topic_id_user_id | 310  | func,const |  1 | Using index; Using where | 
+0

任何指針,以掃描如何避免 – user1590071

+0

它掃描到滿足where條件結合起來。您可能需要在user_id和level和entry_id上創建一些索引作爲開始,以查看它是否會執行索引掃描而不是順序掃描。 – 2012-09-12 16:13:14

回答

3

試試這個:

EXPLAIN 
SELECT  te.topic_id,te.entry_id 
FROM  topic_entry te 
JOIN  topic_user tu ON te.topic_id = tu.topic_id AND tu.user_id = 'xyz' 
WHERE  te.level=4 
AND   te.entry_id > 0 
ORDER BY te.entry_id DESC 
LIMIT 5; 
+0

嘗試加入之前,與此加入它臨時filesort,這也是緩慢 – user1590071

+0

好吧,只是認爲它可能有所幫助,我創建了一個測試模式,並使用您的代碼創建相同的表,但沒有數據,無法準確測試在我的結束查詢。 –

+1

問題可能是您在這兩個表中都有一個由兩列組成的鍵,且沒有設置外鍵關係。 –

0

試着改變你的WHERE子句中鍵的順序:
WHERE te.topic_id in (select topic_id from topic_user where user_id ='xyz') AND te.level=4 AND te.entry_id > 0

WHERE te.topic_id in (select topic_id from topic_user where user_id ='xyz') AND te.entry_id > 0 AND te.level=4
我不是100%肯定(我不能測試它那一刻),但它可能會有所幫助。
原因是MySQL嘗試並且無法將您的密鑰映射到
topic_id, level, entry_idKEY topic_id_2,並且因額外字段而失敗。

P.S.和「狡猾Raskal」有更好的解決方案,或者你可以嘗試這兩種

+0

在更改鍵序列方面沒有區別。不確定,但可能是預處理器處理序列。 – user1590071

0

什麼

explain extended 
select te.topic_id,te.entry_id 
from topic_entry te LEFT JOIN topic_user tu ON 
    te.topic_id = tu.topic_id AND tu.user_id = 'xyz' 
WHERE 1 = 1 
    AND te.level=4 
    AND te.entry_id > 0 
ORDER BY te.entry_id DESC 
LIMIT 5; 
+0

當使用上述查詢 – user1590071

+0

@ user1590071時,您所掃描行數的差異小於1%,您沒有參考約束(由於myisam),而且我也沒有您的數據。不同於你的東西。 – rkosegi