查询优化(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 23是我的优化尝试,让我知道你的想法。

注意*这些不是我实际使用的函数,我使用 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 子句的主要内容,如果未能解决你的问题,请参考以下文章

关于MySQL查询优化

MySQL---sql语句优化

MySQL---sql语句优化

mysql sql优化的一些总结

MySQL SQL语句优化技巧

Mysql sql语句优化经验总结