今日客户现场出现一个查询SQL异常慢的情况。
用时分钟级别。
SELECT *
FROM (SELECT a1.*, rownum rn
FROM (SELECT openOrder.exchId,
............
openOrder.internalbizmark,
customer.typeIdList
FROM openOrder, customer
WHERE openOrder.custId = customer.custId
AND openOrder.orderTime >= 0810000000
AND openOrder.orderTime <= 0811235959
AND openOrder.branchId IN ('001100', '001101')
AND openOrder.acctId IN ('##########')
AND openOrder.optLevel IN ('A0')
AND openOrder.custType IN
('A2', 'A9', 'A1', 'A4', 'A3')
ORDER BY orderTime, serialNum) a1
WHERE rownum <= 100) a2
WHERE rn >= 1;
其中:
openOrder表数据量360万条;
customer表数据量76条;
执行计划利用上了ACCTID索引,但是有大量的NESTED LOOPS,导致异常高的逻辑读。
将SQL中的AND openOrder.acctId IN ('##########')条件取消,SQL查询速度反而变快了,但是走的是全表扫描方式。
突然醒悟,这是两个数据体量差距异常大的表,有严重的数据倾斜。通过openOrder.acctId索引访问,反而代价很大,择全表扫描的效率比选择索引要更高。
改造为:
FROM openOrder left join customer on openOrder.custId = customer.custId
WHERE openOrder.orderTime >= 0810000000
AND openOrder.orderTime <= 0811235959
执行计划虽然走了全表扫描,但是执行效率大幅提升了。