我有一个联系人表,其主键为id。它还有一个辅助索引idx_id_del_user(id,deleted,user_id)。
以下查询使用索引,因此非常快 -
select id
from jts_contacts
where id = '00000402-25c8-7375-e3df-4ec5b66de11d'
and deleted = 0;
以0.0098s
获取1行但是当我使用in子句时,外部查询进入全表扫描。我希望它能使用主键或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
在9s中取出1行
解释计划 -
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选项尝试过它,但它仍然没有使用索引。有关使此查询更快的任何建议吗?
警告:使用连接而不是in子句将起作用,但由于这是来自现有产品的生成查询 - 因此无法更改为使用连接。
答案 0 :(得分:2)
据我所知,IN
遍历所有匹配的记录,并将它们与子句中的值进行比较,一次一行。
因此,您可以做的最好的事情是使用deleted
上的索引,而您只会浏览deleted = 0
的记录。
答案 1 :(得分: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
表中,然后根据该表运行外部查询。
这种模式将我的类似查询的速度从几分钟提高到不到一秒。我没骗你。