SQL 查询非常慢 - 我该如何改进它?
Posted
技术标签:
【中文标题】SQL 查询非常慢 - 我该如何改进它?【英文标题】:SQL query very slow - How can I improve it? 【发布时间】:2016-06-15 19:20:28 【问题描述】:我正在管理一个数据库,我想知道是否有更酷的方法来进行此查询。
我的实际查询:
SELECT * FROM mytable
LEFT JOIN table1 AS m1 ON mytable.idA=m1.K
LEFT JOIN table1 AS m2 ON mytable.idB=m2.K
LEFT JOIN table1 AS m3 ON mytable.idC=m3.K
LEFT JOIN table1 AS m4 ON mytable.idD=m4.K
LEFT OUTER JOIN table2 AS t1 ON mytable.idK1= t1.idK1 AND mytable.idK2= t1.idK2
LEFT OUTER JOIN table3 ON t1.idT = table3.idT
WHERE m1.K = "my_value" OR m2.K = "my_value" OR m3.K = "my_value" OR m4.K = "my_value"
我有一个查询在同一个其他表上进行 4 次连接,因为我可以在字段 idA、idB、idC 或 idD 中获得值。 之后,我与其他表进行其他 2 个联接。
我的问题是: 我可以改进这段代码吗?有没有更聪明的方法或更好的逻辑可以遵循? 非常感谢,即使是理论上的解释。
【问题讨论】:
你的表格有正确的索引吗? 我会 (1) 确保索引 idA 等,并且 (2) 与ON idA=K OR idB=K OR idC=K OR idD=K
进行一次联接,这不是完全相同的登录,但可以做你想做的事。想想吧。
并按名称调用列。 * 太贵了
你对idA
,idB
,idC
,idD
的值做了什么?
通过WHERE
子句将INNER JOIN
s 转换为INNER JOIN
s,你正在扼杀你的LEFT JOIN
s。这与您的表现无关,但您的查询没有在做您认为它正在做的事情。
【参考方案1】:
考虑您可以索引以下哪些列:mytable.idA
、mytable.idB
、mytable.idC
、mytable.idD
、table1.K
、table2.idT
、table2.idT
。
还要考虑是否可以为table2.idK1
和table2.idK2
创建索引;另一个用于mytable.idK1
和mytable.idK2
。
【讨论】:
从长远来看,不建议只为一个查询创建索引。根据表的大小,您最终将至少使表的大小增加一倍(如果您经常访问索引会占用大量磁盘和内存)。当您有 6 个表时,引擎必须计算 6!决策树并对其进行优化。如果您共享整个表格结构和表格状态以查看基数,这将有所帮助。 在推荐任何索引更改之前,请仔细考虑。否则是不负责任的。 表的大小是 mytable 的 250k 值,其他的小于 50k。 @Shago 如何使用和索引?我不知道利弊 @emish89 看看这个答案***.com/a/29842947/2576398【参考方案2】:我试过这样做,执行时间确实更好:
SELECT * FROM (
SELECT * FROM mytable WHERE idA = "my_value" OR idB = "my_value" OR idC = "my_value" OR idD = "my_value"
) as p1
LEFT JOIN table1 AS m1 ON p1.idA=m1.K
LEFT JOIN table1 AS m2 ON p1.idB=m2.K
LEFT JOIN table1 AS m3 ON p1.idC=m3.K
LEFT JOIN table1 AS m4 ON p1.idD=m4.K
LEFT OUTER JOIN table2 AS t1 ON p1.idK1= t1.idK1 AND p1.idK2= t1.idK2
LEFT OUTER JOIN table3 ON t1.idT = table3.idT
现在执行时间是 0.06 秒,之前是 1.5 - 2 秒。
我能引起一些问题吗?查询似乎运行良好
【讨论】:
以上是关于SQL 查询非常慢 - 我该如何改进它?的主要内容,如果未能解决你的问题,请参考以下文章
我将性能计数器的值发送到 Graphite 的方法非常慢。瓶颈是啥?以及如何改进?