2011-12-22 97 views
4

我有一個聯繫人表,它有一個id的主鍵。它也有一個二級索引idx_id_del_user(id,deleted,user_id)。Mysql select in子句不使用索引

下面的查詢使用索引,因此是非常快的 - 在0.0098s

select id 
from jts_contacts 
where id = '00000402-25c8-7375-e3df-4ec5b66de11d' 
and deleted = 0; 

1行中讀取然而,當我使用條款外部查詢進入全表掃描。我期待它使用主鍵或idx_id_del_user。

select * 
from jts_contacts FORCE INDEX (idx_id_del_user) 
where id in 
(select id 
from jts_contacts 
where id = '00000402-25c8-7375-e3df-4ec5b66de11d') 
and deleted = 0 

1行787-9

牽強解釋計劃 -

id, select_type,   table,   type, possible_keys,     key, key_len, ref, rows, Extra 
------------------------------------------------------------------------------------ 
1, 'PRIMARY',   'jts_contacts', 'ALL', '',       '', '',  '', 1127275, 'Using where' 
2, 'DEPENDENT SUBQUERY', 'jts_contacts', 'const', 'PRIMARY,idx_id_del_user', 'PRIMARY', '108', 'const', 1, 'Using index' 

這個表有120萬個記錄和分析表。我已經嘗試過沒有FORCE INDEX選項,但它仍然沒有使用索引。有關使這個查詢更快的任何建議?


警告:使用連接,而不是條款將工作,但因爲這是從現有的產品所生成的查詢 - 它不能被更改爲使用連接。

回答

2

從我所知道的情況來看,IN會遍歷所有匹配記錄,並將它們與條目中的值進行比較,一次一行。

因此,您可以做的最好的方法是使用deleted上的索引,並且您只會查看deleted = 0的記錄。

+0

謝謝。我也嘗試過。然而,刪除只有兩個vlaue 0和1(它不是很有選擇性)。我實際上將響應時間增加到了12秒。我同意答案,但是它不起作用,因爲刪除的索引不是很有選擇性。 – user1112552 2011-12-22 23:07:54

0

我剛剛遇到了同樣的問題,在閱讀Marcus Adams的文章後,我想到了一些基於來自同一張表的數據在表上運行UPDATE時所學到的知識:創建派生表第一,像這樣:

SELECT * FROM jts_contacts WHERE id IN 
(SELECT id FROM 
    (SELECT id FROM jts_contacts WHERE id = '00000402-25c8-7375-e3df-4ec5b66de11d') 
temp) 
AND deleted = 0 

這將首先從內部查詢獲取完整的結果到派生temp表,然後運行基於該外部查詢。

此模式將我的類似查詢的速度從幾分鐘提高到不到一秒。我沒有騙你。