查询优化(MySql/Sql):将函数移出 where 子句
Posted
技术标签:
【中文标题】查询优化(MySql/Sql):将函数移出 where 子句【英文标题】:Query Optimization (MySql/Sql) : Moving functions out of where clause 【发布时间】:2017-07-26 15:31:05 【问题描述】:更新:对于阅读本文的任何人,正如@dnoeth 所述,索引在查询时间方面会产生巨大的差异。在某些情况下,它将行扫描减少到 1 行。您只需选择最适合您的索引风格。 Clustered vs Non Clustered
索引示例:
E.g: create index ix_descr on my_db.media (description asc)
我有一个查询需要很长时间才能运行,它在 where 子句中有很多函数。优化查询的最佳方法是什么?
将函数移出 where 子句并用连接等替换它们?
我在下面给出了几个简单的例子,FIG 2和3是我的优化尝试,让我知道你的想法。
注意*这些不是我实际使用的函数,我使用 dbo.DecryptBlob(m.mediaId) 等。我选择使用下面的函数以使问题更容易掌握。
图 1.)
SELECT
description, id
FROM
my_db.media
where
length(description) = 10
and description like "S%"
and trim(left(m.description,2)) = 'St'
可能的优化
图 2.)(使用 join 和 group by)
SELECT
m.description, m.mediaId
FROM
my_db.media m
inner JOIN
my_db.media m1 ON length(m.description) = 10
and m.description like "S%"
and trim(left(m.description,2)) = 'St'
group by m.mediaId
图 3.)(使用连接和区分)
SELECT distinct
m.description, m.mediaId
FROM
my_db.media m
inner JOIN
my_db.media m1 ON length(m.description) = 10
and m.description like "S%"
and trim(left(m.description,2)) = 'St'
【问题讨论】:
为什么投反对票?请详细说明 。我是否应该以不同的方式表达我的问题,以便引出更多的答案而不是意见? 你可以试试dev.mysql.com/doc/refman/5.7/en/using-explain.html 添加自联接会增加复杂性,无论条件是在 WHERE 还是 ON 中都没有关系,我怀疑是否有改进,应该是效率较低。更好地索引您的数据。顺便说一句,您可以删除LENGTH
和愚蠢的 TRIM(LEFT)
并简化为一个条件:WHERE description like "St________"
@dnoeth 感谢您的建议。
【参考方案1】:
您的起始评论我将其表述为“不要在函数内隐藏索引列,优化器找不到它以使用 INDEX
。”
and description like "S%"
and trim(left(m.description,2)) = 'St'
和
一样and description LIKE "St%"
这样,INDEX(description)
就会很好地工作。检查 length=10 是次要的,并不是真正的问题。它将对该索引进行“范围”扫描。 (如果您不是指“2”和“St”,那么我的评论可能不适用。)
TRIM
-- 清理输入,而不是在SELECT
期间尝试这样做。
在这种情况下,使用JOIN
将显示内容。
在SELECT
列表中未指定mediaId
时执行group by m.mediaId
是“错误的”。所以,我不知道你在图2中的目标是什么。
【讨论】:
如果我别无选择,只能在索引列上使用函数,比如 dbo.DecryptBlob(clientId) 等,对于这种情况,最好的解决方法是什么? "dbo"?这是 MySQL。 是的,这是正确的,假设出于语法和语义目的,我们有 MySQL 等效的 dbo.DecryptBlob(),在这种情况下我可以使用什么解决方法。【参考方案2】:如果您的应用程序经常根据描述的长度进行选择,您应该考虑添加一个包含描述长度的列并在其上创建索引。
【讨论】:
我更关心的是解决将函数移出 where 子句的最佳方法,是否更有益于进行连接、索引等。@Dnoeth 指出连接增加了查询的复杂性,我删除了连接并对列进行了索引,并注意到并提高了性能。 有时人们非常专注于跳出来的解决方案,而不是退后一步去寻找其他可能性。一般来说,如果人们遇到此线程,我想指出您正在考虑的选项并不是解决此类性能问题的唯一方法。以上是关于查询优化(MySql/Sql):将函数移出 where 子句的主要内容,如果未能解决你的问题,请参考以下文章