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

PostgreSQL查询优化求助:现有查询耗时且CTE出现重复数据

PostgreSQL查询优化:解决慢查询与CTE重复数据问题

问题分析

原查询的核心问题:

  • 存在无用的左连接:Users表在查询中未被引用任何字段,左连会额外增加数据处理开销
  • 先关联维度表再聚合,可能因维度表的一对多关系(或数据冗余)导致行膨胀,拖慢分组计算,也是CTE出现重复数据的根源
  • 分组使用位置序号(1)可读性差,且易出错

优化方案

1. 移除无用连接,重构查询逻辑(直接优化版)

先聚合TimeSheet主表数据,再关联维度表获取名称,避免行膨胀:

select 
    agg."monthYear",
    agg."TimeEntryID",
    agg."TotalHours",
    agg."CreatedOn",
    agg."ApplicationID",
    agg."TSTypeCodeID",
    rcv."CodeName" as TSType,
    agg."UserID",
    agg."StatusID",
    st."Status"
from (
    select 
        to_char(ts."SubmittedDate", 'YYYY-MM') as "monthYear",
        MIN(ts."TimeEntryID") as "TimeEntryID",
        SUM(ts."SpentTime") as "TotalHours",
        MAX(ts."CreatedOn") as "CreatedOn",
        ts."ApplicationID",
        ts."TSTypeCodeID",
        ts."UserID",
        ts."StatusID"
    from task_management_v1."TimeSheet" ts
    where 
        ts."ApplicationID" = 34
        and ts."UserID" in ('YXR4318','KXL5356','BXB0448') 
        and ts."StatusID" in (47,44,45,46) 
        and ts."SubmittedDate" > CURRENT_DATE - INTERVAL '3 months' 
    group by 
        ts."UserID", 
        ts."StatusID", 
        ts."ApplicationID",
        to_char(ts."SubmittedDate", 'YYYY-MM'),
        ts."TSTypeCodeID"
) agg
left join task_management_v1."Status" st
    on agg."StatusID" = st."ID"
left join task_management_v1."RefCodeValue" rcv
    on agg."TSTypeCodeID" = rcv."CodeValueID"
order by agg."CreatedOn" desc
limit 25 offset 0;

2. 正确使用CTE的写法(避免重复数据)

如果一定要用CTE,核心是先聚合主表,再关联维度表,而不是先关联再聚合:

with agg_time_sheet as (
    select 
        to_char(ts."SubmittedDate", 'YYYY-MM') as "monthYear",
        MIN(ts."TimeEntryID") as "TimeEntryID",
        SUM(ts."SpentTime") as "TotalHours",
        MAX(ts."CreatedOn") as "CreatedOn",
        ts."ApplicationID",
        ts."TSTypeCodeID",
        ts."UserID",
        ts."StatusID"
    from task_management_v1."TimeSheet" ts
    where 
        ts."ApplicationID" = 34
        and ts."UserID" in ('YXR4318','KXL5356','BXB0448') 
        and ts."StatusID" in (47,44,45,46) 
        and ts."SubmittedDate" > CURRENT_DATE - INTERVAL '3 months' 
    group by 
        ts."UserID", 
        ts."StatusID", 
        ts."ApplicationID",
        to_char(ts."SubmittedDate", 'YYYY-MM'),
        ts."TSTypeCodeID"
)
select 
    ats."monthYear",
    ats."TimeEntryID",
    ats."TotalHours",
    ats."CreatedOn",
    ats."ApplicationID",
    ats."TSTypeCodeID",
    rcv."CodeName" as TSType,
    ats."UserID",
    ats."StatusID",
    st."Status"
from agg_time_sheet ats
left join task_management_v1."Status" st
    on ats."StatusID" = st."ID"
left join task_management_v1."RefCodeValue" rcv
    on ats."TSTypeCodeID" = rcv."CodeValueID"
order by ats."CreatedOn" desc
limit 25 offset 0;

3. 添加性能优化索引

为TimeSheet表创建复合索引,覆盖过滤条件和聚合所需字段,实现索引覆盖扫描,避免回表:

create index idx_timesheet_filter_agg on task_management_v1."TimeSheet"
("ApplicationID", "UserID", "StatusID", "SubmittedDate")
include ("TimeEntryID", "SpentTime", "CreatedOn", "TSTypeCodeID");

关键优化点说明

  • 移除无用连接:Users表未被使用,左连会增加数据行数和IO开销,直接删除即可
  • 先聚合后关联:主表聚合后数据量大幅减少,再关联维度表不会导致行膨胀,彻底解决CTE重复数据问题
  • 索引优化:复合索引精准匹配where条件,include子句包含聚合所需字段,让数据库无需读取主表数据,直接从索引完成计算

内容的提问来源于stack exchange,提问作者Kittu SD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:30:45