求取一个 sql 优化建议

315 天前
 Dlin

先祖留下的 sql 如下:

SELECT
	COUNT(*) 
FROM
	(
	SELECT
		t2.create_time createTime,
		t2.platform,
		t2.id taskId,
		t2.order_id orderId,
		t1.business_contract_no businessContractNo,
		t3.contract_no,
		t4.contract_name 
	FROM
		esign_task_item t1
		INNER JOIN esign_task t2 ON t1.task_id = t2.id
		LEFT JOIN esign_contract t3 ON t3.task_item_id = t1.id
		LEFT JOIN esign_contract_template t4 ON t4.contract_no = t1.contract_template_no 
	WHERE
		t1.business_contract_no IS NOT NULL 
	GROUP BY
		t1.business_contract_no,
		t2.order_id,
		t2.id 
	ORDER BY
	t1.id DESC 
	) TOTAL

这段 sql 其实也是分页插件生成的,先不说 count 很慢的问题。 问题是里面 group by 非常慢,得查 20 秒左右 执行计划如下:

2666 次点击
所在节点    MySQL
21 条回复
chendl111
314 天前
若在执行上述 SQL 语句时 GROUP BY 操作过慢,您可以尝试进行以下优化:

添加索引:对于涉及到 GROUP BY 操作的字段,添加合适的索引可以显著提高查询性能。您可以考虑为 t1.business_contract_no 、t2.order_id 和 t2.id 添加索引。

使用子查询替代 GROUP BY:有时候,使用子查询来替代 GROUP BY 操作可以提高查询性能。您可以尝试将 GROUP BY 子句替换为子查询,然后使用 DISTINCT 关键字来去重。例如:

sql
SELECT COUNT(*)
FROM (
SELECT DISTINCT
t1.business_contract_no,
t2.order_id,
t2.id
FROM
esign_task_item t1
INNER JOIN esign_task t2 ON t1.task_id = t2.id
LEFT JOIN esign_contract t3 ON t3.task_item_id = t1.id
LEFT JOIN esign_contract_template t4 ON t4.contract_no = t1.contract_template_no
WHERE
t1.business_contract_no IS NOT NULL
) AS TOTAL;
这种方式可能会更快,因为 DISTINCT 操作消除了重复行,并且不需要进行全局的 GROUP BY 操作。

请注意,具体的优化策略可能因数据库的结构、数据量和查询需求而异。建议您根据实际情况评估和测试不同的优化方法以获得最佳性能。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/955444

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX