You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何字面ID查询远快于子查询?SQL性能优化求助

问题解答

为什么子查询组合耗时20秒,字面ID查询却瞬间完成?

  • 当使用IN子查询时,数据库查询优化器可能未选择“先执行子查询得到28个ID,再用ID查找customer”的最优路径,反而将子查询逻辑与外层查询合并,执行了低效的关联操作(比如重复扫描表、不必要的嵌套循环),导致整体耗时剧增。
  • 直接传入字面ID时,优化器能明确识别这是一组常量,会直接利用idcustomer的主键索引(假设idcustomer是主键)快速定位对应记录,因此几乎不耗时。

如何在原查询中添加姓名字段且不耗时40秒?

方案1:使用CTE强制分步执行

通过公共表表达式先计算出符合条件的idcustomer集合,再关联customer表获取姓名字段,让优化器明确分步执行逻辑:

WITH filtered_customers AS (
    SELECT c.idcustomer
    FROM sale s 
    INNER JOIN customer c ON c.idCustomer = s.fkCustomer
    WHERE s.dateSale BETWEEN '1700-01-01' AND '2022-01-26'
        AND c.fkCompany = 'b92c5957-9275-4fa5-9970-1a41eb524328'
)
SELECT c.firstname, c.lastname
FROM customer c
JOIN filtered_customers fc ON c.idcustomer = fc.idcustomer;

方案2:优化sale表的索引

原查询中sale表的过滤条件是dateSale,关联条件是fkCustomer,创建组合索引可大幅提升关联效率:

CREATE INDEX idx_sale_datesale_fkcustomer ON sale(dateSale, fkCustomer);

之后直接修改原查询返回姓名字段:

SELECT c.firstname, c.lastname
FROM sale s 
INNER JOIN customer c ON c.idCustomer = s.fkCustomer
WHERE s.dateSale BETWEEN '1700-01-01' AND '2022-01-26'
    AND c.fkCompany = 'b92c5957-9275-4fa5-9970-1a41eb524328';

该索引能让数据库快速筛选出符合日期的sale记录,再通过fkCustomer关联customer表的现有索引,避免RID查找的开销。

方案3:调整查询关联顺序

先从customer表筛选出符合fkCompany的记录,再关联sale表过滤日期,优化器可能选择更高效的执行路径:

SELECT c.firstname, c.lastname
FROM customer c
INNER JOIN sale s ON c.idCustomer = s.fkCustomer
WHERE s.dateSale BETWEEN '1700-01-01' AND '2022-01-26'
    AND c.fkCompany = 'b92c5957-9275-4fa5-9970-1a41eb524328';

配合上述sale表的索引,能进一步提升查询速度。

内容的提问来源于stack exchange,提问作者Danilo Souza Morães

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:07:28