繁体   English   中英

mysql innodb选择偏移慢

[英]mysql innodb select offset slow

我在表中有29900000条记录,偏移消耗了太多的查询执行时间

SELECT * FROM table_records LIMIT 50 OFFSET 1999950
this query taking 33.087 sec

我已将偏移量更改为2000000

SELECT * FROM table_records LIMIT 50 OFFSET 2000000
this query taking 2.030 sec

交代

EXPLAIN SELECT * FROM table_records LIMIT 50 OFFSET 29941250


id | select_type | table         | type   | possible_keys | key     | key_len | ref    |rows     | Extra   
1  | SIMPLE      | table_records | index  | (NULL)        | PRIMARY | 4       | (NULL) |29900771 |         

我已经删除了设置为限制的偏移量

SELECT * FROM table_records LIMIT 50
this query taking 0.002 sec

任何建议或想法赞赏。

这都是关于缓存的。

简而言之, OFFSET糟糕。 它必须读取并忽略所有“偏移”行,然后传递“限制”行。

在跳过行时,它必须获取行 - 如果它们在磁盘上,这需要时间; 如果它们被缓存在RAM中,它会快得多。 (通常快10倍。)

在您的情况下可能发生的情况:第一个查询在RAM中发现很少(如果有)行,因此它必须包含大部分或全部1999950行。

然后你的第二个查询快速扫描1999950行,然后从磁盘中取出最后的50行。 (或者可能最后的50个已经出现,因为I / O的单位是记录的“块”。)

使用LIMIT和/或OFFSETEXPLAIN很少提供任何线索 - 它通常提供表中总行数的估计值

您的示例还有另一个问题......您没有ORDER BY 因此,引擎可以随意提供它喜欢的任何行。 通常它是可预测的,但有时你会得到惊喜。

但是,一旦添加了ORDER BY即使在获取第一条记录之前 ,也可能需要临时表和排序! 也就是说, SELECT ... ORDER BY .. LIMIT 50 可能和所有其他的一样慢 - 如果你按照索引等不方便的顺序进行排序。

了解在分页网页时OFFSET如何糟糕 这包括“记住你离开的地方”的解决方法。 显示了如何有效地获得接下来的1000行,即使在ID中存在间隙。

有一个解决方案可以更快地完成它,但只有当你有一个主键int并且在这个表中没有间隙时它才会起作用。 我的意思是你不允许删除。 在这种情况下,您的查询将如下所示:

SELECT * FROM table_records where id >= 1999950 order by id LIMIT 50;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM