我们都完成了分页–对于UI中的列表和批量处理数据都是明智的。 “从表LIMIT X,Y中选择(列)”。 可能是“从表ORDER BY some_column LIMIT X,Y中选择(列)”。

请注意什么? 尤其是在使用ORM和处理批次时,顺序无关紧要,您可能会忽略ORDER BY子句。 您期望结果按主键排序。 在大多数情况下(尽管不能保证),但是在您解释查询时,您会看到索引未用于查询–执行全表扫描以获取结果,这很慢。 请注意,如果我们省略LIMIT子句,则再次使用全表扫描,但这是您很少要做的事情–即,没有WHERE子句的查询和

没有分页。

因此,规则1:始终使用ORDER BY子句才能使用索引。

对于UI中的列表,通常需要按某些列排序-修改日期,名称等。这还将执行全表扫描,除非您对该列有索引。

因此,规则2:在ORDER BY的列上始终有一个索引

有点明显的事情,但它们可能是项目中潜伏的无声性能问题。 现在出现在不太明显的地方,这令我惊讶。 当使用LIMIT X,Y时,MySQL会扫描整个表(直到X + Y),而不管索引如何。 请注意,即使“类型”(在EXPLAIN的结果中)不是“全部”(全表扫描),而是“索引”,MySQL仍可能扫描大多数行–检查“行”列。 但这也可能会引起误解(在LIMIT的情况下,它显示row =一切,但是在用所需的行数填充结果时停止)。 因此,如果您有LIMIT 100000,则50个MySQL将扫描100050行。 这会使查询变慢(查询时间反映出–偏移量越大,查询时间越长)。 这是由于MySQL无法在行号上保留索引。 它不能使用主键,因为即使它是auto_increment,也存在间隙。 幸运的是,在巨大的表中,通常会有一个WHERE子句,该子句强制使用索引并减少要扫描的行数。 另外,在用户界面中,您很少会查询第100000条记录。 但是无论如何,这都是需要考虑的事情,尤其是在批处理作业需要遍历整个表的情况下。 您分批执行此操作,因为1. ORM可能会将所有内容存储在内存中并只是杀死您的应用程序2.事务将变得很长。

使用WHERE id> X和id <Y(或BETWEEN)

这不能保证每个批次的大小都相同,但这无关紧要。

上面的规则是“经验法则”,而不是“必须做的事”,但是牢记这些规则是很好的。 最重要的是,您应该分析性能,找到特别慢的查询,然后对它们进行解释,并查看如何对其进行优化以及优化的影响。

PS 这是有关索引的MySQL引擎底层细节的演示 。

参考: Bozho的技术博客博客中的JCG合作伙伴 Bozhidar Bozhanov的 MySQL分页警告 。

翻译自: https://www.javacodegeeks.com/2013/01/caveats-with-mysql-pagination.html