当前位置: 代码网 > it编程>数据库>Mysql > MySQL联合索引遇到范围查询问题解决

MySQL联合索引遇到范围查询问题解决

2026年08月05日 Mysql 我要评论
mysql联合索引遇到范围查询1、环境准备-- 查看mysql版本select version();​-- mysql 5.7 联合索引范围查询测试脚本-- 联合索引字段顺序:tenant_id, c

mysql联合索引遇到范围查询

1、环境准备

-- 查看mysql版本
select version();
​
-- mysql 5.7 联合索引范围查询测试脚本
-- 联合索引字段顺序:tenant_id, created_at, status
-- created_at 位于联合索引中间,用于 between、>、<、>=、<= 等范围查询。
create table if not exists order_index_test (
    id bigint unsigned not null auto_increment comment '主键id',
    order_no varchar(32) not null comment '订单号',
    tenant_id bigint unsigned not null comment '租户id',
    created_at datetime not null comment '创建时间',
    status tinyint unsigned not null comment '状态:1待支付,2已支付,3已关闭',
    amount decimal(10, 2) not null comment '订单金额',
    primary key (id),
    unique key uk_order_no (order_no),
    key idx_tenant_created_status (tenant_id, created_at, status)
) engine = innodb
  default charset = utf8mb4
  collate = utf8mb4_general_ci
  comment = '联合索引范围查询测试表';
​
-- 插入50条测试数据。
insert into order_index_test
    (order_no, tenant_id, created_at, status, amount)
values
    ('ord202607010001', 1001, '2026-07-01 09:10:00', 1,  99.00),
    ('ord202607010002', 1001, '2026-07-01 10:20:00', 2, 128.50),
    ('ord202607020003', 1001, '2026-07-02 08:30:00', 1,  59.90),
    ('ord202607020004', 1001, '2026-07-02 11:40:00', 3, 399.00),
    ('ord202607030005', 1001, '2026-07-03 09:15:00', 2, 219.80),
    ('ord202607030006', 1001, '2026-07-03 14:25:00', 1,  35.00),
    ('ord202607040007', 1001, '2026-07-04 07:50:00', 2, 499.99),
    ('ord202607040008', 1001, '2026-07-04 16:05:00', 3,  88.80),
    ('ord202607050009', 1001, '2026-07-05 10:10:00', 1, 129.00),
    ('ord202607050010', 1001, '2026-07-05 18:30:00', 2, 268.00),
    ('ord202607060011', 1001, '2026-07-06 08:45:00', 1,  45.60),
    ('ord202607060012', 1001, '2026-07-06 13:15:00', 3, 688.00),
    ('ord202607070013', 1001, '2026-07-07 09:35:00', 2, 178.90),
    ('ord202607070014', 1001, '2026-07-07 15:55:00', 1,  76.20),
    ('ord202607080015', 1001, '2026-07-08 10:05:00', 2, 340.00),
    ('ord202607080016', 1001, '2026-07-08 19:20:00', 3,  29.90),
    ('ord202607090017', 1001, '2026-07-09 08:10:00', 1, 108.00),
    ('ord202607090018', 1001, '2026-07-09 12:40:00', 2, 508.50),
    ('ord202607100019', 1001, '2026-07-10 09:00:00', 1,  66.60),
    ('ord202607100020', 1001, '2026-07-10 17:10:00', 3, 199.99),
    ('ord202607110021', 1001, '2026-07-11 08:20:00', 2, 320.00),
    ('ord202607110022', 1001, '2026-07-11 14:45:00', 1,  55.50),
    ('ord202607120023', 1001, '2026-07-12 10:30:00', 2, 780.00),
    ('ord202607130024', 1001, '2026-07-13 16:20:00', 3,  89.00),
    ('ord202607140025', 1001, '2026-07-14 11:15:00', 1, 145.80),
​
    ('ord202607010026', 1002, '2026-07-01 09:25:00', 2, 210.00),
    ('ord202607020027', 1002, '2026-07-02 13:35:00', 1,  75.00),
    ('ord202607030028', 1002, '2026-07-03 08:55:00', 3, 430.00),
    ('ord202607040029', 1002, '2026-07-04 12:10:00', 2,  98.90),
    ('ord202607050030', 1002, '2026-07-05 17:45:00', 1, 156.00),
    ('ord202607060031', 1002, '2026-07-06 10:20:00', 2, 620.50),
    ('ord202607070032', 1002, '2026-07-07 14:30:00', 3,  40.00),
    ('ord202607080033', 1002, '2026-07-08 09:40:00', 1, 188.80),
    ('ord202607090034', 1002, '2026-07-09 18:05:00', 2, 275.00),
    ('ord202607100035', 1002, '2026-07-10 07:35:00', 1,  68.00),
    ('ord202607110036', 1002, '2026-07-11 11:50:00', 3, 399.90),
    ('ord202607120037', 1002, '2026-07-12 15:10:00', 2, 125.00),
    ('ord202607130038', 1002, '2026-07-13 09:45:00', 1,  49.90),
    ('ord202607140039', 1002, '2026-07-14 13:25:00', 2, 580.00),
    ('ord202607150040', 1002, '2026-07-15 16:40:00', 3, 230.00),
​
    ('ord202607010041', 1003, '2026-07-01 08:15:00', 1,  39.90),
    ('ord202607020042', 1003, '2026-07-02 12:25:00', 2, 149.00),
    ('ord202607030043', 1003, '2026-07-03 16:35:00', 3, 299.00),
    ('ord202607040044', 1003, '2026-07-04 10:45:00', 1,  79.80),
    ('ord202607050045', 1003, '2026-07-05 14:55:00', 2, 450.00),
    ('ord202607060046', 1003, '2026-07-06 19:05:00', 1,  90.00),
    ('ord202607070047', 1003, '2026-07-07 11:15:00', 3, 520.00),
    ('ord202607080048', 1003, '2026-07-08 15:25:00', 2, 170.50),
    ('ord202607090049', 1003, '2026-07-09 09:35:00', 1,  65.00),
    ('ord202607100050', 1003, '2026-07-10 13:45:00', 2, 310.00);
-- 验证数据总数,应返回50。
select count(*) as total_rows
from order_index_test;
​
-- 查看索引定义。
show index from order_index_test;

2、执行计划

2.1 等值查询

explain
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at = '2026-07-03 00:00:00'            
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 14

extra: using index condition

2.2 > < 左开右开查询

explain 
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at > '2026-07-03 00:00:00'
  and created_at <  '2026-07-11 00:00:00'
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 13

extra: using index condition

2.3 >, <= 左开右闭查询

explain 
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at > '2026-07-03 00:00:00'
  and created_at <=  '2026-07-11 00:00:00'
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 14

extra: using index condition

2.4 >= , < 左闭右开查询

explain
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at >= '2026-07-03 00:00:00'
  and created_at <  '2026-07-11 00:00:00'
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 14

extra: using index condition

2.5 >= , <= 左闭右闭查询

explain 
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at >= '2026-07-03 00:00:00'
  and created_at <=  '2026-07-11 00:00:00'
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 14

extra: using index condition

2.6 between and 查询

explain
select id, order_no, tenant_id, created_at, status, amount
from order_index_test
where tenant_id = 1001
  and created_at between '2026-07-03 00:00:00' and '2026-07-11 00:00:00'
  and status = 1;

执行计划:

关键字段:

key: idx_tenant_created_status

key_len: 14

extra: using index condition

3、总结

  • between><>=<= 都是范围条件,都可以使用索引。
  • 联合索引遇到中间列的范围查询后,范围列本身仍然使用索引。
  • 范围列后面的字段通常不能像前置等值字段一样缩小整个连续扫描区间。
  • 后续字段仍可能参与范围边界计算,并通过 icp 在索引层过滤,所以不能简单地说“范围查询后面的索引全部失效”。
  • key_len=14 不代表 status 对范围内所有记录都完成了精准定位,还需要结合 using index condition 和扫描行数判断。

范围查询不会让联合索引后面的列完全失效,但会限制后续列继续缩小连续扫描范围;后续列可能参与边界计算和 icp 过滤,是否真正高效需要结合数据量和执行计划判断。

到此这篇关于mysql联合索引遇到范围查询问题解决的文章就介绍到这了,更多相关mysql联合索引内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com