Skip to content

面试速答(先看这里)

**一句话结论:**MySQL 的limit m n工作原理就是先读取前面m+n条记录,然后抛弃前m条,然后返回后面n条数据,所以m越大,偏移量越大,性能就越差。

60秒标准回答:

不一样,这是MySQL中典型的深度分页的问题

MySQL 的limit m n工作原理就是先读取前面m+n条记录,然后抛弃前m条,然后返回后面n条数据,所以m越大,偏移量越大,性能就越差

所以, limit 10000000,100要比limit 0,100的性能差的多,因为他要先读取10000100条数据,然后再抛弃前面的10000000条

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**所以, limit 10000000,100要比limit 0,100的性能差的多,因为他要先读取10000100条数据,然后再抛弃前面的10000000条。
  • **要点2:**通常,我们在查询数据的时候,如果明确的知道我们想要多少行的话,那么建议大家在查询语句中使用limit,而不是把整个结果集查出来再自己丢弃那些不用的数据。
  • **要点3:**虽然我们前面提过,深度分页的时候,MySQL自己也是先全都查出来,再丢弃的,但是,MySQL针对limit也是有一些优化的。
  • **要点4:**1、MySQL通常更愿意执行全表扫描,但是如果你用LIMIT只查询几行记录的话,MySQL在某些情况下可能会使用索引。
  • **要点5:**5、如果ORDER BY不走索引,而且后面还带了LIMIT的话,那么优化器可能可以避免用一个合并文件,并使用内存中的filesort操作对内存中的行进行排序。

**记忆锚点:**MySQL → limit → LIMIT → row_count → ORDER → order

关键取舍:

  • MySQL 的limit m n工作原理就是先读取前面m+n条记录,然后抛弃前m条,然后返回后面n条数据,所以m越大,偏移量越大,性能就越差。
  • 所以, limit 10000000,100要比limit 0,100的性能差的多,因为他要先读取10000100条数据,然后再抛弃前面的10000000条。

易错提醒:

  • 5、如果ORDER BY不走索引,而且后面还带了LIMIT的话,那么优化器可能可以避免用一个合并文件,并使用内存中的filesort操作对内存中的行进行排序。
  • 一个好的办法就是排序的时候不要只用一个字段,可以再加一个字段,比如id字段这种一定不会重复的。

加分表达:

  • 通常,我们在查询数据的时候,如果明确的知道我们想要多少行的话,那么建议大家在查询语句中使用limit,而不是把整个结果集查出来再自己丢弃那些不用的数据。
  • 虽然我们前面提过,深度分页的时候,MySQL自己也是先全都查出来,再丢弃的,但是,MySQL针对limit也是有一些优化的。
  • 但是下面我们要介绍的优化前提都是使用limit的同时没有用having语句。

追问准备:

  • 围绕「MySQL」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「limit」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「LIMIT」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

不一样,这是MySQL中典型的深度分页的问题。

MySQL的limit m n工作原理就是先读取前面m+n条记录,然后抛弃前m条,然后返回后面n条数据,所以m越大,偏移量越大,性能就越差。

📄 ✅limit的原理是什么?

打开文档:✅limit的原理是什么?

所以,limit 10000000,100要比limit 0,100的性能差的多,因为他要先读取10000100条数据,然后再抛弃前面的10000000条。

📄 ✅MySQL的深度分页如何优化

打开文档:✅MySQL的深度分页如何优化

扩展知识 ​

limit优化 ​

通常,我们在查询数据的时候,如果明确的知道我们想要多少行的话,那么建议大家在查询语句中使用limit,而不是把整个结果集查出来再自己丢弃那些不用的数据。

虽然我们前面提过,深度分页的时候,MySQL自己也是先全都查出来,再丢弃的,但是,MySQL针对limit也是有一些优化的。但是下面我们要介绍的优化前提都是使用limit的同时没有用having语句。(参考https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html、https://dev.mysql.com/doc/refman/8.4/en/limit-optimization.html)

1、MySQL通常更愿意执行全表扫描,但是如果你用LIMIT只查询几行记录的话,MySQL在某些情况下可能会使用索引。

2、如果你将LIMIT row_count子句与ORDER BY子句组合在一起使用的话,MySQL会在找到排序结果的row_count行数据后后立即停止排序,而不是对整个结果进行排序。如果使用索引来完成排序,这将非常快。

> 当ORDER BY子句使用了索引时,MySQL就能够基于已经排好序的索引树快速找到所需的前N行数据,而不需要对整个表进行全表扫描和排序了。

3、如果LIMIT row_count与DISTINCT一起使用,一旦找到row_count惟一的行,MySQL就会停止。

4、LIMIT 0 可以快速返回一个空的结果集,这是用来检测一个查询是否有效的一种很有用的方法。

5、如果ORDER BY不走索引,而且后面还带了LIMIT的话,那么优化器可能可以避免用一个合并文件,并使用内存中的filesort操作对内存中的行进行排序。

limit 和 order by ​

我们知道,当我们在查询的时候,对某个字段order by时,如果这个字段有一些重复值,那么MySQL会是可以自由的以任意顺序返回这些行记录的,并且根据总体的执行计划而有有不同的表现。也就是说,排序结果可能是不固定的。

所以,当order by语句中,有Limit的时候,可能每次的查询结果都不一样。比如有下面两次查询的结果可能就不一样:

latex
mysql> SELECT * FROM ratings ORDER BY category;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  3 |        2 |    3.7 |
|  4 |        2 |    3.5 |
|  6 |        2 |    3.5 |
|  2 |        3 |    5.0 |
|  7 |        3 |    2.7 |
+----+----------+--------+
latex
mysql> SELECT * FROM ratings ORDER BY category LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  4 |        2 |    3.5 |
|  3 |        2 |    3.7 |
|  6 |        2 |    3.5 |
+----+----------+--------+

那么该怎么解决呢?一个好的办法就是排序的时候不要只用一个字段,可以再加一个字段,比如id字段这种一定不会重复的。

latex
mysql> SELECT * FROM ratings ORDER BY category,id LIMIT 5;

​