当前位置: 首页 > 面试题库 >

为什么在查询中使用LIMIT时MySQL变慢?

燕光熙
2023-03-14
问题内容

我试图弄清楚为什么我的查询之一变慢以及如何解决它,但是我对结果有些困惑。

我有一个orders约80列和775179行的表,并且正在执行以下请求:

SELECT * FROM orders WHERE id_state = 2 AND id_mp IS NOT NULL ORDER BY creation_date DESC LIMIT 200

在4.5秒内返回38行

删除时,ORDER BY我得到了很好的改进:

SELECT * FROM orders WHERE id_state = 2 AND id_mp IS NOT NULL LIMIT 200

0.30秒内38行

但是,如果在LIMIT不触摸的情况下删除,ORDER BY我会得到更好的结果:

SELECT * FROM orders WHERE id_state = 2 AND id_mp IS NOT NULL ORDER BY creation_date DESC

0.10s(??)中的38行

为什么我的LIMIT这么饿?

继续前进

在尝试发送答案之前,我尝试了一些尝试,并注意到我有一个索引creation_date(是datetime),因此我删除了它,并且第一个查询现在以0.10s的速度运行。这是为什么

编辑

很好的猜测,我在where的其他列上有索引。

mysql> explain SELECT * FROM orders WHERE id_state = 2 AND id_mp IS NOT NULL ORDER BY creation_date DESC LIMIT 200;
+----+-------------+--------+-------+------------------------+---------------+---------+------+------+-------------+
| id | select_type | table  | type  | possible_keys          | key        | key_len | ref  | rows | Extra       |
+----+-------------+--------+-------+------------------------+---------------+---------+------+------+-------------+
|  1 | SIMPLE      | orders | index | id_state_idx,id_mp_idx | creation_date | 5       | NULL | 1719 | Using where |
+----+-------------+--------+-------+------------------------+---------------+---------+------+------+-------------+

设置1行(0.00秒)

mysql> explain SELECT * FROM orders WHERE id_state = 2 AND id_mp IS NOT NULL ORDER BY creation_date DESC;
+----+-------------+--------+-------+------------------------+-----------+---------+------+-------+----------------------------------------------------+
| id | select_type | table  | type  | possible_keys          | key       | key_len | ref  | rows  | Extra                                              |
+----+-------------+--------+-------+------------------------+-----------+---------+------+-------+----------------------------------------------------+
|  1 | SIMPLE      | orders | range | id_state_idx,id_mp_idx | id_mp_idx | 3       | NULL | 87502 | Using index condition; Using where; Using filesort |
+----+-------------+--------+-------+------------------------+-----------+---------+------+-------+----------------------------------------------------+

问题答案:

索引不一定能提高性能。为了更好地了解正在发生的事情,如果您explain为不同的查询包括了,这将有所帮助。

我最好的猜测是您有一个索引,id_state甚至id_state, id_mp可以用来满足该where子句。如果是这样,则不order by使用的第一个查询将使用此索引。它应该很快。即使没有索引,这也需要对orders表中的页面进行顺序扫描,这仍然可以非常快。

然后当您添加索引时creation_date,MySQL决定使用该索引代替order by。这需要读取索引中的每一行,然后获取相应的数据页以检查where条件并返回列(如果存在匹配项)。该读取效率极低,因为它不是按“页面”顺序,而是按索引指定的顺序。随机读取可能效率很低。

更糟糕的是,即使您有一个limit,您仍然必须读取 整个
表,因为需要整个结果集。尽管您已经保存了38条记录的排序,但是您创建了一个效率非常低下的查询。

顺便说一句,如果orders表无法容纳在可用内存中,这种情况将变得更加严重。然后,您有一个称为“崩溃”的条件,其中每个新记录都倾向于生成一个新的I /
O读取。因此,如果一个页面上有100条记录,则该页面可能必须被读取100次。

通过在上添加索引,可以使所有这些查询的运行速度更快orders(id_state, id_mp, creation_date)。该where子句将使用前两列,而order by则将使用最后两列。



 类似资料:
  • 问题内容: 如标题所述,我想要一个解决方法… 干杯 问题答案: 您可能会希望将an添加到嵌套查询中。

  • 问题内容: 我正在尝试编写一个函数,该函数采用下面编写的函数中编写的变量,然后在 MySQL 查询中使用该变量。我在下面写了一个例子: 当我尝试运行该程序时,出现以下错误: 这是用于大学作业,必须使用格式来接收变量。我花了数小时在互联网上搜索,试图找到解决方案,请帮助:/ 问题答案:

  • 问题内容: 简而言之,场景:一个拥有超过1600万条记录[2GB大小]的表。当使用ORDER BY * primary_key *时,SELECT的LIMIT偏移量越高,查询速度就越慢 所以 花费不到 那只订购30条记录,并且无论如何都相同。因此,这不是ORDER BY的开销。 现在,当获取最新的30行时,大约需要180秒。如何优化该简单查询? 问题答案: 通常,较高的偏移量会使查询速度变慢,因为

  • 问题内容: 我正在写一个存储过程,其中有一个名为 my_size 的输入参数,它是一个 INTEGER 。我希望能够在语句的子句中使用它。显然,这不受支持,是否有解决方法? 问题答案: 通过搜索找到了这篇文章。我在下面粘贴了相关文本。 这是一个论坛帖子,显示了准备好的语句的示例,可让您将变量值分配给limit子句: http://forums.mysql.com/read.php?98,12637

  • 问题内容: 我想将表中的行从1001开始更新到下一个1000。 我尝试了以下查询: 这给了我语法错误。它是否正确?我在这里犯任何错误吗? 我们可以这样限制更新吗? 另外,我尝试更新的行的数据类型为INTEGER的列p_id具有Null值。因此,我什至无法使用以下查询进行更新: 我上面的查询正确吗? 要做到这一点怎么办? 问题答案: 处理null时,不匹配null值。您可以使用或 可以与但只能一起使

  • 问题内容: 我正在使用Codeigniter执行分页功能,但我认为这通常适用于PHP / mySQL编码。 我正在使用offset和limit检索目录列表,具体取决于每页要多少结果。但是要知道所需的总页数,我需要知道(结果总数)/(限制)。现在,我正在考虑第二次运行SQL查询,然后计算所需的行数,但不使用LIMIT。但是我认为这似乎是在浪费计算资源。 有没有更好的方法?谢谢! 编辑:我的SQL查询