面试官:MySQL BETWEEN AND 语句包括边界吗?

使用数据库时,我们经常会用到范围查询,今天来聊一聊 MySQL 的 BETWEEN AND 语句。

1.是否包含边界

为了说明 BETWEEN AND 语句是否包括边界,我们先创建一张表,SQL 如下:

复制
CREATE TABLE`test3` ( `id`int(8) NOTNULL AUTO_INCREMENT, `a`varchar(10) COLLATE utf8_bin DEFAULTNULL, `b`varchar(10) COLLATE utf8_bin DEFAULTNULL, `date`dateDEFAULTNULL, `date_time` datetime DEFAULTNULL, `time_stamp`timestampNULLDEFAULTNULL, PRIMARY KEY (`id`), KEY`idx_a` (`a`) ) ENGINE=InnoDB AUTO_INCREMENT=11DEFAULTCHARSET=utf8 COLLATE=utf8_bin1.2.3.4.5.6.7.8.9.10.

我们插入 10 条数据,如下图:

图片

图片

1.1 执行结果

对 id 做范围查询
复制
SELECT * FROM test3 WHERE id BETWEEN 2 AND 6;1.

查询结果如下:

图片

图片

可以看到,对 id 做范围查询,包含了边界值 2 和 6,是一个闭区间。

对 date 做范围查询
复制
SELECT * FROM test3 WHERE DATE BETWEEN 2025-08-28 AND 2025-08-31;1.

查询结果如下:

图片

图片

可以看到,对 date 类型的字段进行范围查询,同样包含了边界值,是一个闭区间。

对 date_time 做范围查询
复制
SELECT * FROM test3 WHERE date_time BETWEEN 2025-08-28 AND 2025-08-31;1.

对 date_time 使用日期做范围查询,查询结果如下:

图片

图片

可以看到,这个查询漏掉了 2025-08-31 这一天的数据,是一个前闭后开的区间。

这是因为 MySQL 会自动将日期的时间部分补充为零点,所以上面的查询语句等价于:

复制
SELECT * FROM test3 WHERE date_time BETWEEN 2025-08-28 00:00:00 AND 2025-08-31 00:00:00;1.

为了不漏掉数据,可以将上面的查询语句改为:

复制
SELECT * FROM test3 WHERE DATE BETWEEN 2025-08-28 AND 2025-09-01;1.

对 time_stamp 使用日期做范围查询,结果跟 date_time 一样。

1.2 总结

BETWEEN AND 语句是包括边界值的,是一个前闭后闭的区间。BETWEEN A AND B 等价于 >= A AND <= B。注意时间类型的字段,DATETIME 和 TIMESTAMP,如果采用日期格式来查询,结果是前闭后开的区间。BETWEEN A AND B 等价于 >= A AND < B。为了避免漏掉数据,datetime 和 timestamp 使用日期做范围查询,可以在后面的日期上加 1 天。

2.原理

2.1 执行器优化

对于 BETWEEN AND 语句,MySQL 优化器会在早期优化时把它优化成等值查询,所以下面查询 SQL

复制
SELECT * FROM test3 WHERE id BETWEEN 2 AND 6;1.

在优化器看来完全等价与:

复制
SELECT * FROM test3 WHERE id >= 2 AND id <= 6;1.

两个 SQL 在性能上没有差别。

2.2 性能

索引范围扫描

如果 BETWEEN AND 语句的字段上有索引,则可以使用索引进行范围扫描,效率很高。我们看一下上面一个 SQL 执行计划如下:

复制
EXPLAIN SELECT * FROM test3 WHERE id BETWEEN 2 AND 6;1.

图片

图片

type=range,代码使用到了索引进行范围扫描,查询过程如下:

存储引擎从索引树的根节点开始,找到第一个 id >= 2 的索引条目。这个操作时间复杂度是 O(log n),非常高效;从上面找到的第一个索引条目开始,沿着索引树的叶子节点向后顺序扫描;当遇到第一个 id > 6 的索引条目时,停止扫描;存储引擎给执行器返回结果集。全表扫描

如果 BETWEEN AND 语句的字段上没有索引,只能进行全表扫描,比如下面的语句:

复制
EXPLAIN SELECT * FROM test3 WHERE b BETWEEN 30 AND 50;1.

我们看一下执行计划:

图片

图片

这就需要扫描表中的每一行记录,逐一判断字段 b 的值是否落在 [30, 50] 这个区间内。这个执行效率非常低。

非主键索引跟等值查询不同的是,即使 BETWEEN AND 语句的字段加了普通索引,如果查询的字段用不上覆盖索引,也会走全表扫描。如下面的语句:

复制
EXPLAIN SELECT * FROM test3 WHERE a BETWEEN 30 AND 50;1.

虽然字段 a 上面有普通索引,但是查询的是表 test3 中的所有字段,也是走不上 a 这个索引的。我们看一下执行计划:

图片

复合索引

我们再看一下复合索引的情况,我们新建一张表,SQL 如下:

复制
CREATE TABLE`test4` ( `id`int(8) NOTNULL AUTO_INCREMENT, `a`varchar(10) COLLATE utf8_bin DEFAULTNULL, `b`varchar(10) COLLATE utf8_bin DEFAULTNULL, `date`dateDEFAULTNULL, `date_time` datetime DEFAULTNULL, `time_stamp`timestampNULLDEFAULTNULL, PRIMARY KEY (`id`), KEY`idx_a_b` (`a`, `b`) ) ENGINE=InnoDB AUTO_INCREMENT=11DEFAULTCHARSET=utf8 COLLATE=utf8_bin1.2.3.4.5.6.7.8.9.10.

在 test4 这张表上,我们建一个字段(a,b)的复合索引。 BETWEEN AND 语句是可以用最左前缀原则的。如果我们执行下面 SQL:

复制
SELECT a,b,id FROM test4 WHERE a BETWEEN 2 AND 6 AND b = 3;1.

复合索引的第一列 a 使用了范围查询,第二列 b 作等值查询。MySQL 可以利用索引快速找到字段 a 在范围[2, 6]之间的数据,然后在这些结果中筛选出 b = 3 的记录。这种情况下字段 a 使用了索引,但是字段 b 没有用上索引。

图片

如果我们执行下面 SQL:

复制
SELECT a,b,id FROM test4 WHERE a = 3 and b BETWEEN 2 AND 6;1.

复合索引的第一列 a 使用了等值查询,第二列 b 做范围查询。这种情况也是可以走上索引的。

图片

如果我们执行下面 SQL:

复制
SELECT a,b,id FROM test4 WHERE b BETWEEN 2 AND 6;1.

这种情况不符合最左前缀原则,所以是走不上索引的。

图片

索引下推

使用 BETWEEN AND 语句不能走索引下推。

我们再来创建一张表:

复制
CREATE TABLE`test_temp` ( `id`INT(11) NOTNULLDEFAULT0, `a`VARCHAR(20) DEFAULTNULL, `b`VARCHAR(10) DEFAULTNULL, `c`VARCHAR(10) DEFAULTNULL, `d`VARCHAR(10) DEFAULTNULL, PRIMARY KEY (`id`), KEY`a_b`(`a`,`b`) ) ENGINE=INNODBDEFAULTCHARSET=utf81.2.3.4.5.6.7.8.9.

插入几条数据

复制
INSERT INTO test_temp VALUES(100, 10, 20, 2, 1); INSERT INTO test_temp VALUES(200, 10, 40, 4, 2); INSERT INTO test_temp VALUES(300, 10, 30, 3, 3); INSERT INTO test_temp VALUES(400, 40, 10, 1, 4);1.2.3.4.

如果我们执行下面的 SQL,是不能走索引下推的:

复制
EXPLAIN SELECT * FROM test_temp WHERE a BETWEEN 10 AND 50 AND b < 50;1.

执行计划如下:

图片

图片

而如果我们把 SQL 改成:

复制
EXPLAIN SELECT * FROM test_temp WHERE a >= 10 AND a <= 50 AND b < 50;1.

执行计划如下:

图片

图片

可以看到,用上了索引下推。

3 总结

本文介绍了 BETWEEN AND 语句的用法、原理和性能,希望对你理解这个范围查询语句有所帮助 。

阅读剩余
THE END