下面从建表开始准备同一批数据。两条查询都用 FORCE INDEX 固定选择 idx_created_at;这个提示只用于控制实验变量,不是生产优化的默认写法。
DROP TABLE IF EXISTS orders_index_demo;
CREATE TABLE orders_index_demo (
id BIGINT PRIMARY KEY,
tenant_id BIGINT NOT NULL,
status VARCHAR(16) NOT NULL,
created_at DATETIME NOT NULL,
amount DECIMAL(12,2) NOT NULL,
INDEX idx_created_at (created_at)
) ENGINE=InnoDB;
INSERT INTO orders_index_demo VALUES
(101,7,'PAID','2026-08-31 23:50:00',18.00),
(205,7,'PAID','2026-09-01 09:20:00',88.00),
(309,7,'PAID','2026-09-01 10:05:00',39.00),
(412,7,'PAID','2026-09-01 11:40:00',120.00),
(490,7,'REFUND','2026-09-01 15:00:00',55.00),
(501,8,'NEW','2026-09-01 18:30:00',65.00),
(520,8,'PAID','2026-09-02 00:00:00',75.00),
(601,8,'PAID','2026-09-02 12:00:00',99.00);
-- A:先扫描索引记录,再逐条计算 DATE()
EXPLAIN ANALYZE SELECT id
FROM orders_index_demo FORCE INDEX (idx_created_at)
WHERE DATE(created_at)='2026-09-01';
-- B:直接形成左闭右开的时间范围
EXPLAIN ANALYZE SELECT id
FROM orders_index_demo FORCE INDEX (idx_created_at)
WHERE created_at>='2026-09-01 00:00:00'
AND created_at<'2026-09-02 00:00:00';
预期现象:A 无法由普通列索引直接算出日期范围,通常要检查整棵指定索引中的 8 条记录;B 可以把扫描边界锁定在当天的 5 条记录。小数据用于验证计划形态,不代表生产耗时。