2013-07-23 53 views
0

我有这样的SQL:如何优化这个SQL在MySQL

select t1.id,t1.type from collect t1 
where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid='1146') 
limit 1; 

是是好的,但如果我用一个指示命令其表现似乎不太好和:

select t1.id,t1.type from collect t1 
where t1.type='1' and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid='1146') 
order by t1.id asc 
limit 1; 

它变得更糟。 我如何优化这个?

这里解释一下:

id | select_type  | table | type | possible_keys | key | key_len | ref    | rows | Extra      | 
+----+--------------------+-------+------+---------------+-----+---------+-----------------+------+-----------------------------+ 
| 1 | PRIMARY   | t1 | ref | i2,i1,i3  | i1 | 4  | const,const  | 99 | Using where; Using filesort | 
| 2 | DEPENDENT SUBQUERY | t2 | ref | i5   | i5 | 65  | img.t1.id,const | 2 | Using where; Using index 
+0

这是因为数学正在做的很慢。你有没有试过把'和t1.total>(t1.totalComplate + t1.totalIng)'放在'limit'的最前面,以减小操作执行结果集的大小? – AgmLauncher

+0

你定义了哪些索引? – eggyal

+0

没有Agmlauncher,我没有试过,怎么样? –

回答

1

1)如果它没有这样做,在collect.id列定义索引可以(如果id对于任何两条线都不相同):

CREATE UNIQUE INDEX idx_collect_id ON collect (id); 

也许你需要一个collect_log.tidcollect_log.bid的索引。甚至在两列,就像这样:

CREATE INDEX idx_collect_log_tidbid ON collect (tid, bid); 

让它UNIQUE是否有意义,那就是,如果没有两行的值相同的(TID,BID)夫妇在表中。例如,如果这些疑问给出相同的结果,它可能可能:

SELECT count(*) FROM collect_log; 

SELECT count(DISTINCT tid, bid) FROM collect_log; 

但是不要让它UNIQUE如果您不确定这是什么意思。

2)验证列的类型collect.typecollect.statuscollect_log.bid。在您的查询中,您将它们与字符串进行比较,但也许它们被定义为INT(或SMALLINTTINYINT ...)?在这种情况下,我建议你放弃数字周围的引号,因为与整数比较相比,字符串比较非常缓慢。

select t1.id,t1.type from collect t1 
where t1.type=1 and t1.status=1 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and id not in(
      select tid from collect_log t2 
       where t2.tid=t1.id and t2.bid=1146) 
order by t1.id asc 
limit 1; 

3)如果仍然没有帮助,只是增加EXPLAIN在您的查询的面前,你会得到执行计划。将结果粘贴到此处,我们可以帮助您理解它。其实,我建议你在之前做这个步骤创建任何新的索引。

+0

非常感谢你,我添加了log.tid,bid的索引,但它是Normal类型。好吧,它工作正常,性能变好。我应该把它改为独特吗?和UNIQUE或NORMAL短缺? –

+0

我已经粘贴在这个页面上的解释。 –

+0

我更新了我的答案,以解决有关UNIQUE的问题。 –

-1

我会尝试使用 INNERLEFT JOIN首先摆脱IN声明。

像这样(未经):

CREATE INDEX idx_collect_id ON collect (id); 

也可能是唯一索引,如果您:

select t1.id,t1.type 
from collect t1 
    LEFT JOIN collect_log t2 ON t1.id = t2.tid 
where t1.type='1' 
    and t1.status='1' 
    and t1.total>(t1.totalComplate+t1.totalIng) 
    and NOT t2.bid = '1146' 
order by t1.id asc 
limit 1; 
+0

此查询不会给出相同的结果,它在语义上不等于原始查询。在collect_log表中没有id = X的行的情况下,您的查询不会从collect表中返回行id = X。原始查询返回该行。在这种情况下,依赖子查询可以代替IN(...),例如:... AND NOT EXISTS(从collect_log t2中选择1,其中t2.tid = t1.id和t2.bid = 1146) – krokodilko

+0

对。但是,LEFT JOIN而不是INNER JOIN将返回该行。 – Deruijter