偏差限制(“LIMIT 500000,10”)即使在指数后仍然很慢?

时间:2011-12-11 20:13:09

标签: mysql performance indexing limit

我有一个包含int字段的表格,我们称之为createTime。该表包含数百万条记录。现在我想运行查询:

select * from `table` order by `createTime` desc limit 500000, 10

我为createTime创建了一个索引,但查询运行缓慢。什么原因?我该如何改进呢?

这是EXPLAIN所说的:

id 1
select_type simple
table table
type index
possible_keys null
key createTime
key_len 4
ref null
rows 500010
extra

至于偏移量,当它很小时,它的工作速度会快得多。

3 个答案:

答案 0 :(得分:9)

一般规则:avoid OFFSET for large tables

  

[A] s偏移量增加,查询执行所需的时间   逐渐增加,这可能意味着处理非常大的表   将需要很长时间。原因是偏移起作用   在表中没有索引的行的物理位置。所以   要在偏移x处找到一行,数据库引擎必须遍历   从0到x的所有行。

  

一般的经验法则是“绝不使用限制条款中的偏移”。对于   小桌子你可能不会注意到任何差异,但有桌子   有超过一百万行你会看到巨大的表现   增加。

答案 1 :(得分:2)

如果您有唯一的列,则可以加快速度。理想情况下,它将是createTime本身:

SELECT "table".*
  FROM "table"
  INNER JOIN (
    SELECT "createTime"
      FROM "table"
      ORDER BY "createTime" DESC
      LIMIT 500000, 10
  ) AS "limit" ON "table"."createTime" = "limit"."createTime"

如果createTime不是唯一的,但是您有另一个唯一的列,那么您可能会发现需要在createTime和另一列上创建复合索引,以便此查询有效运行:

SELECT "table".*
  FROM "table"
  INNER JOIN (
    SELECT "createTime", "unique"
      FROM "table"
      ORDER BY "createTime" DESC
      LIMIT 500000, 10
  ) AS "limit" ON "table"."unique" = "limit"."unique"

答案 2 :(得分:0)

我认为索引不会改变任何东西。使用offset, limit表示“读取偏移量+限制数据集并丢弃它们(数量偏移量)”。如果你真的想要为这么大的表分页或类似的东西,你应该使用一种方法,你可以在查询的WHERE部分限制你的结果。这些类型的查询将受益于正确的索引。

使用日期时,解决方案可能是使用时隙来显示数据。例如。您可以显示一周中每一天的链接,并构建您的查询,例如“WHERE createDate>'2011-12-11'and crateDate<'2011-12-12'。