使用“NOT IN”优化MySQL查询

时间:2014-06-05 14:22:27

标签: php mysql sql sql-optimization

我已经看到了一些涉及" NOT IN"在MySQL查询中,但我没有设法重现建议的解决方案。

所以我有一些搜索引擎。它从非常简单的查询开始,然后尝试更复杂的查询,如果它没有找到足够的结果。以下是伪代码的工作原理

list_of_ids = do_simple_search()
nb_results = size_of(list_of_ids)

if nb_results < max_nb_results :
    list_of_ids .= do_search_where_id_not_in(list_of_ids)

    if nb_results < max_nb_results :
         list_of_ids .= do_complicated_search_where_id_not_in(list_of_ids)

希望我清楚。 无论如何,这里的查询速度很慢,如MySQL-slow所示:

SELECT DISTINCT c.id 
FROM clients c LEFT JOIN communications co ON c.id = co.client_id 
WHERE (co.titre LIKE 'S' OR co.contenu LIKE 'S') AND c.id NOT IN(N)
LIMIT N, N

这是对该查询的解释:

id  select_type     table   type    possible_keys               key         key_len ref             rows    Extra
1   SIMPLE          c       index   PRIMARY                     PRIMARY     2       NULL            25250   Using where; Using index; Using temporary
1   SIMPLE          co      ref     qui_com,id_client,titre     id_client   2       klients.c.id    8       Using where; Distinct

MySQL版本为5.1.63-0ubuntu0.11.04.1-log

也许我的方法在这里错了?你会怎么做?感谢。

1 个答案:

答案 0 :(得分:1)

几句话:

1)为什么要左右加入i / o(内部)加入? LEFT JOIN意味着您还希望获得与客户不匹配的记录,这是意图吗?如果没有,则JOIN i / o LEFT JOIN更快。

2)如果你只是这样做,为什么你需要加入:

SELECT DISTINCT co.client_id from communications co 
WHERE (co.titre LIKE 'S' OR co.contenu LIKE 'S') AND co.id!=N LIMIT N,N;

另外,如果你进行JOIN,两个连接的字段必须是索引,否则它也很慢。

更重要的是,你从通信表中调整了client_id和id,但是这两者都没有共同的索引,这意味着执行查询的工作量更多(因此using temporary通常不是一个好兆头)

3)你在co.titre和co.contenu上做了一个复杂的条件,你似乎有索引,但它们没有被使用。这意味着这部分可能很慢。