我有一个包含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
至于偏移量,当它很小时,它的工作速度会快得多。
答案 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'。