要优化这个SQL查询,尤其是避免Using temporary
和Using filesort
,可以考虑以下几种方法:
索引优化:
- 确保在连接和过滤条件上使用了合适的索引。
- 对于
ORDER BY
和GROUP BY
字段,考虑创建覆盖索引。
查询重写:
- 使用子查询或CTE(公用表表达式)来预先计算数量,从而避免在
GROUP BY
和ORDER BY
中直接使用聚合函数。
以下是优化后的SQL查询示例:
-- 首先,创建一个覆盖索引来加速查询
CREATE INDEX idx_biz_work_order_label_optimized
ON biz_work_order_label (deleted, label_type, work_order_id)
WHERE deleted = 0;
CREATE INDEX idx_biz_work_order_optimized
ON biz_work_order (deleted, problem_location_code, reporting_time, nature, id)
WHERE deleted = 0;
-- 然后,使用子查询来计算数量,并排序
WITH RequestWorkOrderCounts AS (
SELECT
t.label_name AS topic,
t.label_id,
COUNT(t1.id) AS requestWorkOrderNumber
FROM
biz_work_order_label t
INNER JOIN biz_work_order t1 ON t.work_order_id = t1.id
WHERE
t.deleted = 0
AND t1.deleted = 0
AND t.label_type = 8
AND t1.problem_location_code LIKE '%440000%'
AND t1.reporting_time BETWEEN '2024-01-01 00:00:00' AND '2024-12-31 23:59:59'
AND t1.nature IN ('ts', 'jb')
GROUP BY
t.label_name,
t.label_id
)
SELECT
topic,
label_id,
requestWorkOrderNumber
FROM
RequestWorkOrderCounts
ORDER BY
requestWorkOrderNumber DESC
LIMIT 10;
解释:
索引创建:
biz_work_order_label
表的索引idx_biz_work_order_label_optimized
包括了deleted
, label_type
, 和work_order_id
,并过滤deleted = 0
。biz_work_order
表的索引idx_biz_work_order_optimized
包括了deleted
, problem_location_code
, reporting_time
, nature
, 和id
,并过滤deleted = 0
。
查询重写:
- 使用CTE(
WITH
子句)RequestWorkOrderCounts
预先计算每个label_name
和label_id
的请求工作单数量。 - 在外层查询中,仅对预先计算的结果进行排序和限制,从而避免在
GROUP BY
和ORDER BY
中直接使用聚合函数。
这种方法通过减少查询中的临时表和文件排序操作,可以显著提高查询性能。确保在生产环境中测试这些更改,并根据实际情况调整索引和查询结构。
确保在以下列上有索引
优化后的SQL语句