【问题标题】:mysql slow query when results are less than limit当结果小于限制时mysql慢查询
【发布时间】:2016-09-16 14:43:57
【问题描述】:

我有一个包含 550.000 条记录的表

SELECT * FROM logs WHERE user = 'user1' ORDER BY date DESC LIMIT 0, 25

此查询需要 0.0171 秒。没有LIMIT,有3537个结果

SELECT * FROM logs WHERE user = 'user2' ORDER BY date DESC LIMIT 0, 25

此查询需要 3.0868 秒。没有LIMIT,有13个结果

表键是:

PRIMARY KEY  (`id`),
KEY `date` (`date`)

当使用“LIMIT 0,25”时,如果记录少于 25 条,查询会变慢。我该如何解决这个问题?

【问题讨论】:

  • 你索引你的表了吗? LIMIT 也应该是 25 我看不出 0 的作用。
  • 这可能与this Question 类似,本质上表明这是从查询优化器中选择错误的索引。尝试使用explain 进行检查,然后您可以在查询中使用index hints 修复它。
  • @MikeTung LIMIT 0,25OFFSET LIMIT 对的缩写。它只是意味着25 records, starting at record 0
  • @makadev IGNORE INDEX (date) 工作,谢谢

标签: mysql


【解决方案1】:

使用limit 25 允许查询在找到25 行时停止。

如果在 550.000 行中有 3537 行匹配,则平均而言,假设分布相等,在检查 550.000/3537*25 rows = 3887 rows 后,在按 date 排序的列表中找到 25 行(date 上的索引)或根本没有排序的列表。

如果您在 550.000 行中有 13 个匹配行,limit 25 将必须检查所有 550.000 行(即行数的 141 倍),因此我们期望0.0171 sec * 141 = 2.4s。显然还有其他因素决定运行时间,但数量级合适。

还有一个额外的效果。不幸的是,date 的索引不包含user 的值,因此 MySQL 必须在原始表中查找该值,方法是在该表中来回跳转(因为数据本身是按主键排序的) .这比直接读取无序表要慢。

实际上,如果您有很多行要读取,则根本不使用索引可能比使用索引更快。您可以通过使用例如强制 MySQL 不使用它。 FROM logs IGNORE INDEX (date),但这将导致它现在必须在绝对每种情况下读取整个表:最后一行可能是最新的,因此必须在结果集中,因为您按 date 订购。因此,它可能会减慢您的第一个查询 - 快速读取完整的 550.000 行可能比通过来回跳跃缓慢读取 3887 行要慢。 (MySQL 事先也不知道这一点,所以它做出了选择——对于您的第二个查询显然是错误的)。

那么如何获得更快的结果呢?

有一个按user 排序的索引。然后'user2' 的查询可以在 13 行后停止,因为它知道没有更多行了。现在这将比查询 'user1' 更快,后者必须查看 3537 行,然后通过 date 对它们进行排序。

因此,您的查询的最佳索引将是 user, date,因为它知道何时停止查找更多行并且列表已经按照您想要的方式排序(并且在所有情况下都超过了 0.0171)。

索引也需要一些资源(例如,更新表时需要硬盘空间和时间来更新索引),因此为每个查询添加完美的索引有时可能会适得其反。

【讨论】:

    猜你喜欢
    • 2022-10-19
    • 2019-11-22
    • 2014-09-17
    • 2011-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    相关资源
    最近更新 更多