我有一个像这样的SQL:
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 :(得分:1)
1)如果尚未完成,请在collect.id
列上定义索引:
CREATE INDEX idx_collect_id ON collect (id);
如果可以的话,或者可能是唯一的索引(如果id
对于任何两行都不相同):
CREATE UNIQUE INDEX idx_collect_id ON collect (id);
也许您需要collect_log.tid
或collect_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;
但如果你不确定它意味着什么,不要让它变得独一无二。
2)验证列collect.type
,collect.status
和collect_log.bid
的类型。在您的查询中,您将它们与字符串进行比较,但它们可能被定义为INT
(或SMALLINT
或TINYINT
...)?在这种情况下,我建议你删除数字周围的引号,因为与整数比较相比,字符串比较非常缓慢。
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,即可获得执行计划。将结果粘贴到此处,我们可以帮助您理解它。实际上,我建议你在创建任何新索引之前执行这一步。
答案 1 :(得分:-1)
我首先尝试使用 INNER IN
删除LEFT JOIN
语句。
像这样(未经测试):
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;