MySQL排序速度优化

3

这里有两个样本。

在第一个示例中,使用orderby时可以更快地获得结果。(根据phpmyadmin的速度报告)

在另一个示例中,我没有使用order by,结果比较慢。(根据phpmyadmin的速度报告)

使用Orderby会快速获取结果,这不合理吗?

对我来说,排名并不重要,速度才是最重要的。

select bayi,tutar 
from siparisler 
where durum='1' and MONTH(tarih) = MONTH(CURDATE()) and YEAR(tarih) = YEAR(CURRENT_DATE()) 
order by id desc

速度:0.0006

select bayi,tutar
from siparisler 
where durum='1' and MONTH(tarih) = MONTH(CURDATE()) and YEAR(tarih) = YEAR(CURRENT_DATE())

速度:0.7785


@Julia 带着某些东西来是一回事,排序和带来则是另外一回事。 - othermember
执行计划的比较显示了什么? - PM 77-1
@PM 77-1 的速度已经写在上面了。 - othermember
“执行计划”将展示查询的实现方式,并帮助您解释其中的差异。 - PM 77-1
查询缓存是否已开启?请尝试使用 SQL SQL_NO_CACHE ... 再次查询。 - Rick James
4个回答

3
一条带有 order by 子句的查询将永远不会比同一查询不带 order by 子句执行得更快。对行进行排序会增加数据库的工作量。在最理想的情况下,排序变成无操作,因为 MySQL 在第一次正确顺序检索行,但这只是使两个查询在性能方面等价(并不能使排序查询更快)。
可能,order by 的结果已被缓存,因此MYSQL会直接从缓存中给出结果,而不实际执行查询。
如果性能最重要,请尝试更改 tarih 列上的日期函数使用方法,以避免使用 where 谓词:这样的构造会阻止数据库利用索引(我们称谓词为非SARGable)。请考虑:
select bayi, tutar 
from siparisler 
where 
    durum = 1 
    and tarih >= dateformat(current_date, '%Y-%m-01')
    and tarih <  dateformat(current_date, '%Y-%m-01') + interval 1 month
order by id desc

为了提高此查询的性能,考虑在 (durum, tarih, id desc, bay, tutar) 上建立索引:它应该作为一个覆盖索引行为,MySQL 可以使用它来执行整个查询,甚至不需要查看实际数据。

所以这是来自缓存的数据。 因此,orderby会减慢使用速度吗? - othermember
@othermember:是的 - 或者至少,正如我在回答中所解释的那样,它不会加速查询。 - GMB
在MySQL中,如何为任何表定义默认的“按id降序排序”? - othermember
@GMB……我不认为这一定是正确的。在某些情况下,可能会选择非常不同的执行计划,而这恰好更快。 - Gordon Linoff
@GMB - 你提到的是“查询缓存”,在8.0版本中已经被取消了。我猜测在记录时间时它可能是开启状态。 - Rick James
显示剩余3条评论

2

在0.0006秒时,你几乎可以确定正在测量查询缓存的性能而不是执行时间。尝试使用 SELECT SQL_NO_CACHE 重新运行这两个查询,并查看性能差异。


1

首先,我建议将查询编写为:

select bayi, tutar 
from siparisler p
where durum = 1 and -- no quotes assuming this is an integer 
      tarih >= curdate() - interval (1 - day(curdate()) day;

这可以利用索引(durm,tarih)

但这不是你的问题。 order by可能会导致完全不同的执行计划。 这是假设性的,但目的是解释可能发生的情况。

让我假设以下内容:

  • 表仅具有索引(id desc,durum,tarih)
  • where子句匹配少数行。
  • 行非常宽。

没有order by的查询可能会生成一个完整的表扫描执行计划。 由于行很宽,会读取大量不必要的数据。

带有order by的查询可以按顺序读取数据,然后应用 where条件。 这比其他版本更快,因为只读取与where条件匹配的行。

我不能保证这正在发生。 但是对于查询,存在一些反直觉的情况。


将整数字面量与整数列进行比较时,加上引号不会影响性能。 - Rick James

0

您可以通过EXPLAIN命令进行分析,然后检查与类型字段、索引或全部相对应的值。

示例:

EXPLAIN SELECT bayi,tutar 
FROM siparisler 
WHERE durum='1' AND MONTH(tarih) = MONTH(CURDATE()) AND YEAR(tarih) = YEAR(CURRENT_DATE()) 
ORDER BY id DESC;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接