MySQL ORDER BY CASE 优化

Posted

技术标签:

【中文标题】MySQL ORDER BY CASE 优化【英文标题】:MySQL ORDER BY CASE optimization 【发布时间】:2018-10-22 13:27:34 【问题描述】:

我查看了互联网,但找不到此特定查询的解决方案。我有这个问题:

SELECT *
FROM profile
ORDER BY CASE WHEN country_geoname_id = 2635167 
              THEN 1 ELSE 0 END DESC, 
         score DESC

我想知道是否可以通过避免文件排序来优化此查询。我为列(country_geoname_idscore)创建了一个索引,但没有帮助。

解释选择:

【问题讨论】:

这张桌子上有什么索引? ^^ 请同时发布此查询的EXPLAIN SELECT *...SHOW CREATE TABLE profile 您只想在顶部显示一条特定记录,并以任何其他顺序显示所有其他记录?为什么不直接选择该记录并与数据集的其余部分(减去该记录)合并? 此表包含所有配置文件,有多个 country_geoname_id = 2635167 的配置文件。我需要首先显示具有该 geonameId 的所有配置文件(按分数排序),然后,所有配置文件与其他 geonameIds(也按分数排序)。稍后我将使用 EXPLAIN SELECT 编辑问题。 也许您可以创建一个 UNION :您首先使用 WHERE country_geoname_id = 2635167 条件进行选择,然后使用 WHERE country_geoname_id 2635167 条件创建另一个选择。这样您将首先获得您想要的,然后是另一个 【参考方案1】:

当您将订单条件放入函数中时,您将其设置为不可存储。

What makes a SQL statement sargable?

如果你想使用索引创建一个额外的布尔字段isMyCountry 并为它创建一个索引

然后你的查询变成了:

SELECT *
FROM profile
ORDER BY isMyCountry, 
         score DESC

【讨论】:

我想过这个解决方案,但问题是订单中的ID参数是动态的,根据您所在的路线,它是不同的ID。 然后将该信息添加到问题中。但如果是这种情况,你就无法让它发挥作用。正如我在链接上向您展示的那样,当您在无法使用索引的情况下使用函数时。 你需要 mysql 8.0 来创建一个可以工作的索引:INDEX(isMyCountry ASC, score DESC)。简单的解决方法是翻转isMyCountry 的含义,使两列都是DESC。然后任何版本的 MySQL 以及 INDEX(isMyCountry, score) 都可以使用。

以上是关于MySQL ORDER BY CASE 优化的主要内容,如果未能解决你的问题,请参考以下文章

order by limit 造成优化器选择索引错误

mysql GROUP BY、DISTINCT、ORDER BY语句优化

Mysql之order by|group by 排序优化

MySQL调优--05---多表查询优化子查询优化 ORDER BY优化GROUP BY优化分页查询优化

MySQL-SQL优化:主键,order by,group by,limit,count,update

MySQL高级--- ORDER BY优化