Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 带偏移量的限制(“限制500000,10”)即使在索引之后也很慢?_Mysql_Performance_Indexing_Limit - Fatal编程技术网

Mysql 带偏移量的限制(“限制500000,10”)即使在索引之后也很慢?

Mysql 带偏移量的限制(“限制500000,10”)即使在索引之后也很慢?,mysql,performance,indexing,limit,Mysql,Performance,Indexing,Limit,我有一个带有int字段的表,我们称它为createTime。这个表由几百万条记录组成。现在我要运行查询: select * from `table` order by `createTime` desc limit 500000, 10 我已经为createTime创建了一个索引,但是查询运行速度非常慢。原因是什么?我怎样才能改进它 解释是这样说的: id 1 select_type simple table table type index possible_keys null key cr

我有一个带有
int
字段的表,我们称它为
createTime
。这个表由几百万条记录组成。现在我要运行查询:

select * from `table` order by `createTime` desc limit 500000, 10
我已经为
createTime
创建了一个索引,但是查询运行速度非常慢。原因是什么?我怎样才能改进它

解释是这样说的:

id 1
select_type simple
table table
type index
possible_keys null
key createTime
key_len 4
ref null
rows 500010
extra
至于偏移量,它在小的时候工作得更快。

一般规则:

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

一般的经验法则是“在限制条款中永远不要使用偏移量”。对于 小桌子你可能不会注意到任何区别,但是有桌子 超过一百万行,您将看到巨大的性能 增加


我认为索引不会改变任何事情。使用
offset,limit
表示“读取offset+限制数据集并丢弃(偏移数量)”。如果您真的希望对如此大的表进行分页或类似的操作,那么应该使用一种方法,在该方法中可以在查询的where部分限制结果。这些类型的查询将受益于适当的索引


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

如果您有一个唯一的列,则可以加快查询速度。理想情况下,它应该是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"

你试过使用EXPLAIN关键字来查看MySql在做什么吗?实际上,EXPLAIN select*from
table
order by
createTime
desc limit 500000,10。出于兴趣,createTime是什么数据类型?我已经在问题中解释过它是一个int。EXPLAIN说没有什么有趣的,它使用的是创建的索引,并进行了估计到500010的行数。(创建索引之前的性能如何?没有偏移量的限制如何?偏移量较小的限制如何?)@塞巴斯蒂安诺瓦克:为什么不向我们展示一下
解释
所说的内容呢?既然你要求对数据进行其他解释……对不起,我的意思是一个典型的createTime列包含哪些内容-一些示例值。另外,你在使用ISAM、InnoDB吗?我更喜欢“避免大偏移量”“@ypercube:但是对于小表来说,大的
偏移量
是可以的。你的意思是偏移量大于表的大小?是的,我想是的。我的评论(可能过于敏感)是因为我觉得那篇文章的标题有点误导。在大型表中使用具有适当索引的小偏移量是可以的。@TomalakGeret'kal:你会用什么来代替OFFSET或OFFSET in LIMIT?谢谢,但是这个查询仍然需要几秒钟的时间。对于一个网站来说,这是不可接受的。基于createTime列实现分页难道没有更快的方法吗?