乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

LIMIT

导学

查询结果可能有成千上万条,但用户一次只能看一页。LIMIT 是 MySQL 提供的分页利器,也是控制返回结果数量的最简洁方式。

定义

LIMIT:MySQL 特有的子句(非 SQL 标准),用于限制 SELECT 语句返回的行数。通常与 ORDER BY 配合使用,实现分页查询。

注意:SQL 标准使用 FETCH FIRST,Oracle 使用 ROWNUM,SQL Server 使用 TOP。MySQL 和 PostgreSQL 使用 LIMIT。

核心语法

-- MySQL 5.7 两种写法
SELECT 列 FROM 表 LIMIT 数量;
SELECT 列 FROM 表 LIMIT 偏移量, 数量;
SELECT 列 FROM 表 LIMIT 数量 OFFSET 偏移量;

演示数据准备

DROP TABLE IF EXISTS employees;

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前 employees 表中的完整数据如下:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

SQL 示例

场景一:只取前 N 条

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept, score FROM employees
ORDER BY score DESC, emp_id ASC
LIMIT 2;

操作后结果:

emp_namedeptscore
大翔技术部100
白歌技术部NULL

结果解读:先按 score 降序排列(相同分数再按 emp_id 升序),然后只取前 2 条。由于表中只有 2 条数据,因此返回全部记录。注意:没有 ORDER BY 的 LIMIT 返回的"前 N 条"是不确定的,因为物理存储顺序不可预测。

场景二:分页查询(第 1 页,每页 2 条)

当前数据状态:见上文 employees 表完整数据,已按 score 降序、emp_id 升序排列。

执行语句:

SELECT emp_name, dept, score FROM employees
ORDER BY score DESC, emp_id ASC
LIMIT 0, 2;
-- 等价于
-- LIMIT 2 OFFSET 0;

操作后结果:

emp_namedeptscore
大翔技术部100
白歌技术部NULL

结果解读:LIMIT 0, 2 表示跳过 0 行,取 2 行,即第 1 页的数据。由于表中只有 2 条数据,因此返回全部记录。

场景三:分页查询(第 2 页,每页 2 条)

当前数据状态:见上文 employees 表完整数据,已按 score 降序、emp_id 升序排列。

执行语句:

SELECT emp_name, dept, score FROM employees
ORDER BY score DESC, emp_id ASC
LIMIT 2, 2;
-- 等价于
-- LIMIT 2 OFFSET 2;

操作后结果:

emp_namedeptscore

结果解读:LIMIT 2, 2 表示跳过前 2 行,取接下来的 2 行,即第 2 页的数据。由于表中只有 2 条数据,因此没有数据返回。

场景四:分页查询(第 3 页,每页 2 条)

当前数据状态:见上文 employees 表完整数据,已按 score 降序、emp_id 升序排列。

执行语句:

SELECT emp_name, dept, score FROM employees
ORDER BY score DESC, emp_id ASC
LIMIT 4, 2;
-- 等价于
-- LIMIT 2 OFFSET 4;

操作后结果:空结果集(0 行)。

结果解读:跳过前 4 行,取接下来的 2 行。由于表中只有 2 条数据,因此没有数据返回。

分页公式:LIMIT (页码 - 1) * 每页条数, 每页条数

场景五:获取第 N 高的绩效分(经典面试题)

当前数据状态:见上文 employees 表完整数据。

执行语句:

-- 获取绩效分第 2 高的员工
SELECT emp_name, score FROM employees
ORDER BY score DESC, emp_id ASC
LIMIT 1, 1;

操作后结果:

emp_namescore
白歌NULL

结果解读:先按 score 降序排列(相同分数按 emp_id 升序),跳过前 1 条(大翔 100),取第 2 条,即白歌 NULL。

场景六:LIMIT 0 的妙用

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, score FROM employees
WHERE dept = '技术部'
ORDER BY score DESC
LIMIT 0;

操作后结果:空结果集(0 行)。

结果解读:LIMIT 0 不返回任何数据行,但会返回结果集的列结构(列名、类型)。这在程序化地探测 SQL 语法正确性和结果集元数据时非常有用,比返回大量数据再丢弃要高效得多。

LIMIT 的性能陷阱

深度分页问题

执行语句(糟糕示例):

-- 糟糕:偏移量100万时极慢
SELECT * FROM employees
ORDER BY emp_id ASC
LIMIT 1000000, 10;

结果解读:MySQL 仍然需要扫描/排序前 1,000,010 行,然后丢弃前 1,000,000 行。偏移量越大,性能越差。

优化方案:使用覆盖索引 + 延迟关联

为了演示这个优化,我们假设有一张更大的表,其核心思路是:

-- 优化:利用主键索引减少回表
SELECT s.* FROM employees s
INNER JOIN (
    SELECT emp_id FROM employees
    ORDER BY emp_id ASC
    LIMIT 1000000, 10
) tmp ON s.emp_id = tmp.emp_id;

结果解读:子查询只取 emp_id(索引列),避免了深度分页时的回表开销,外层再通过主键关联取完整数据。这是处理大数据量深度分页的经典优化手段。

常见误区

误区正解
LIMIT 可以不配合 ORDER BY合法但不推荐,结果顺序不确定,分页会混乱。
LIMIT 能减少服务器计算量LIMIT 只在最后阶段截断结果,前面的扫描、排序、连接操作一样不少。
深度分页(大 OFFSET)和浅分页一样快偏移量越大性能越差,需用延迟关联等技巧优化。
LIMIT 是 SQL 标准LIMIT 是 MySQL 扩展,标准 SQL 使用 FETCH FIRST。

面试考点

Q:LIMIT 在 SQL 执行顺序中的位置?

LIMIT 是最后执行的步骤,在 ORDER BY 之后。它只影响返回给客户端的行数,不影响查询过程中的计算量。

Q:MySQL 深度分页怎么优化?

  1. 业务上限制最大页码(如只能翻到 100 页);2. 使用"记录上一页最后 ID"的方式代替 OFFSET;3. 延迟关联(Deferred Join),先 LIMIT 取主键,再关联取完整行。

Q:LIMIT 0 有什么用?

快速验证 SQL 语法和获取结果集结构(列名、类型),而不返回任何数据行。常用于程序化的元数据探测。

Q:MySQL 中 LIMIT 10 和 LIMIT 0, 10 有什么区别?

没有区别。LIMIT 10 是 LIMIT 0, 10 的简写,都表示从第 1 行开始取 10 行。

小结

  • LIMIT 用于限制返回行数,是 MySQL 分页的核心工具
  • 分页公式:LIMIT (page-1)*size, size
  • 深度分页(大 OFFSET)性能差,需要优化
  • 始终配合 ORDER BY 使用,确保分页顺序稳定
  • LIMIT 0 可用于获取结果集结构而不返回数据

下一章引子:学会了筛选、排序、分页,接下来深入了解 WHERE 子句中的各种运算符。

上一页
ORDER BY
下一页
COUNT