近日解决一线上查询性能问题,发现使用了基于id子查询的limit语句。如下:
SQL1: 基于id子查询、两个索引条件的limit语句
SELECT *
FROM order_status
WHERE vendor_code IN ( 'bk0857', 'bk0001' )
AND createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 18:00:00'
AND id <= (SELECT id
FROM order_status
WHERE vendor_code IN ( 'bk0857', 'bk0001' )
AND createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 18:00:00'
ORDER BY id DESC
LIMIT 10, 1)
ORDER BY id DESC
LIMIT 10;
该语句执行120s+未返回, 将子查询直接替换成id具体值,查询性能依然没有改观(由此推断不是子查询性能问题)。查看其explain结果如下:
SQL2: 不带id的子查询、两个索引条件的limit语句:
SELECT *
FROM order_status
WHERE vendor_code IN ( 'bk0857', 'bk0001' )
AND createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 23:59:59'
ORDER BY createtime DESC
LIMIT 10, 10;
该语句1s左右即可返回。其explain结果如下:
减少vendor_code查询条件后测试结果。
SQL3: 基于id子查询、一个索引条件的limit语句:
SELECT *
FROM order_status
WHERE createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 18:00:00'
AND id <= (SELECT id
FROM order_status
WHERE createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 18:00:00'
ORDER BY id DESC
LIMIT 10, 1)
ORDER BY id DESC
LIMIT 10;
50+ms内查询出结果,explain结果:
SQL4: 不带id子查询、一个索引条件的limit语句:
SELECT *
FROM order_status
WHERE createtime >= '2022-03-17 00:00:00'
AND createtime <= '2022-03-17 23:59:59'
ORDER BY createtime DESC
LIMIT 10, 10;
40-ms内查询出结果,explain结果:
根据以上SQL执行结果分析:
- 在未使用子查询的情形下,都使用了idx_createtime索引,所以查询性能较快。
- 在使用子查询的情形下,主查询如果只有一个索引条件,查询性能依旧很快(估计索引依旧起作用)。
- 在使用子查询的情形下,主查询如果使用了两个以上的索引条件,则只有一个索引生效,其他索引作为条件进行过滤,因此影响了效率。