使用IN子句为10,000条记录优化mysql查询

时间:2014-01-17 09:55:03

标签: mysql performance query-optimization

EDITED: 所以这是我使用的查询:

    SELECT *
    FROM contacts
   WHERE id in
       (
    SELECT DISTINCT contacts.id
    from contacts INNER
   JOIN contacts2tags ON contacts.id = contacts2tags.contactid
   WHERE ( tagid in ( 178 ) ) )

它运行得很慢。建议优化吗? 我添加了索引,但仍需要改进!

联系人表包含id,first_name,last_name,..和标记表包含id,name。 contacts2tags 表包含contactid和tagid,分别与contacts.id和tags.id相同 说明: enter image description here

请查看:optimise mysql query with LIKE operator for 10k records

我在这里发布一部分查询是愚蠢的。抱歉:P

5 个答案:

答案 0 :(得分:0)

我只是比较了查询 选择基准(1000000,1 in in(1,2,3,4,5));花了0.122秒左右 选择基准(1000000,(1 = 1或1 = 2或1 = 3或1 = 4或1 = 5));花了0.088秒

所以你可以尝试使用或代替我不确定但是对于索引也没有使用所以只是试一试。

答案 1 :(得分:0)

使用或代替IN。

您的查询应该是:    SELECT c.id FROM contacts c inner join contacts2tags t on c.id = t.contactid WHERE (t.tagid = 7 or t.tagid = 4) GROUP BY c.id HAVING count(distinct t .tagid)= 2

答案 2 :(得分:0)

您向我们展示的计划表明,优化程序只需要获取3行数据。如果它“慢”(你没说多慢),那么可能是计划不是最优的,或者你的数据非常偏斜。

我要检查的第一件事是索引统计数据是否是最新的。然后我试试......

SELECT count(*)
  FROM contacts c
inner join contacts2tags t 
  on c.id = t.contactid 
   WHERE t.tagid in (7,4)

了解DBMS实际处理的行数以解析查询。如果这个数字非常高,那么调整查询就不太可能带来很大的性能提升。

....但是一个可能的解决方案是......

SELECT c.id 
FROM contacts c,
  contacts2tags t4,
  contacts2tags t7,
WHERE c.id = t4.contactid
AND c.id = t7.contactid
AND t4.contactid=t7.contactid
AND t4.tagid=4
AND t7.tagid=7;

答案 3 :(得分:0)

无法在更新的查询中看到使用子查询的必要性。请尝试以下操作(尽管最好使用联系人而不是联系人所需列的名称。*)。

SELECT DISTINCT contacts.*
FROM contacts 
INNER JOIN contacts2tags ON contacts.id = contacts2tags.contactid
WHERE tagid IN ( 178 )

确保contacts2tags表上的tagid上有索引。

如果contacts2tags上的contactid / tagid是唯一的(我希望这样),则不需要DISTINCT。这可以通过在tagid / contactid上添加唯一覆盖索引来强制执行(按此顺序允许在WHERE子句中使用此密钥)。

答案 4 :(得分:0)

我想知道你为什么要在子查询中首先加入联系人和contacts2tags,然后再用它来过滤联系人!?!

我认为原因是你已经将DISTINCT优化​​到id(精益)id字段而不是之后在整个联系人上进行。*记录。

无论如何,你真正应该做的事情恕我直言如下:

SELECT *
 FROM contacts
WHERE EXISTS ( SELECT *
                 FROM contacts2tags 
                WHERE contacts2tags.contactid = contacts.id
                  AND tagid in ( 178 ) )

这不会使联系人记录加倍,因为查询处理器知道它可以在contacts2tags表中找到第一个匹配后停止搜索。

至于使用IN()vs使用OR ...我怀疑它会产生很大的不同,因为在内部它可能会被转换为相同的东西(?!)