优化oraclesql查询 Oracle SQL性能调优

优化oraclesql查询 Oracle SQL性能调优,sql,oracle,optimization,query-optimization,sql-tuning,Sql,Oracle,Optimization,Query Optimization,Sql Tuning,有人能帮我优化这个查询吗? (请注意,我在select语句中有多个子查询,为了方便起见,我这里只提供两个子查询) 我在这里提供了解释计划,并将添加表的详细信息 (在这种情况下,我将SQL server DTS包转换为Oracle过程。因此,所有表都是由我创建的,几乎没有索引。) 列的基数: TABLE_NAME COLUMN_NAME NUM_DISTINCT GM_TEMP_VEHICLECOUNTBYDA PK_DA_VC 54936 GM_TEMP_VEHICLECOUNTB

有人能帮我优化这个查询吗? (请注意,我在select语句中有多个子查询,为了方便起见,我这里只提供两个子查询)

我在这里提供了解释计划,并将添加表的详细信息

(在这种情况下,我将SQL server DTS包转换为Oracle过程。因此,所有表都是由我创建的,几乎没有索引。)

列的基数:

TABLE_NAME  COLUMN_NAME NUM_DISTINCT
GM_TEMP_VEHICLECOUNTBYDA    PK_DA_VC    54936
GM_TEMP_VEHICLECOUNTBYDA    VEHICLECOUNT_IN 660
GM_TEMP_VEHICLECOUNTBYDA    REPORTYEAR_IN   6
GM_TEMP_VEHICLECOUNTBYDA    REPORTMONTH_IN  2
GM_TEMP_VEHICLECOUNTBYDA    GMCUSTOMTYPECODE_VC 2
GM_TEMP_VEHICLECOUNTBYDA    GMCUSTOMDETAILEDSEGMENTCODE_VC  72
GM_TEMP_VEHICLECOUNTBYDA    GMCUSTOMWEIGHTGROUPNAME_VC  4
GM_TEMP_VEHICLECOUNTBYDA    GMCUSTOMEMANUFACTURERNAME_VC    47
GM_TEMP_VEHICLECOUNTBYDA    GENERICMANUFACTURERNAME_VC  48
GM_TEMP_VEHICLECOUNTBYDA    GMPRIMARYCODE_VC    3
GM_TEMP_VEHICLECOUNTBYDA    MAKEDESCRIPTION_VC  71
GM_TEMP_VEHICLECOUNTBYDA    GMCUSTOMIMPORTDOMESTICNAME_VC   2
MAEDEALERGUIDEFILE  PK_DEALERCODE_VC    511
MAEDEALERGUIDEFILE  STATUSCODE_VC   4
MAEDEALERGUIDEFILE  OPFLAG_VC   2
MAEDEALERGUIDEFILE  STATUSNAME_VC   2
MAEDEALERGUIDEFILE  DEALERNAME_VC   502
MAEDEALERGUIDEFILE  DEALERNAMESHORT_VC  509
MAEDEALERGUIDEFILE  ZONECODE_VC 3
MAEDEALERGUIDEFILE  ZONENAME_VC 3
MAEDEALERGUIDEFILE  SALESTERRITORYCODE_VC   14
MAEDEALERGUIDEFILE  GMMACODE_VC 7
MAEDEALERGUIDEFILE  GMMANAME_VC 7
MAEDEALERGUIDEFILE  GMMALEVELCODE_VC    9
MAEDEALERGUIDEFILE  GMMAGROUPKEY    39
MAEDEALERGUIDEFILE  OUTOFVOLUME 24
MAEDEALERGUIDEFILE  RANK    1
MAEDEALERGUIDEFILE  MMACODE_VC  20
MAEDEALERGUIDEFILE  MMANAME_VC  20
MAEDEALERGUIDEFILE  NATIONALCODE_VC 1
MAEDEALERGUIDEFILE  NATIONALNAME_VC 1
MAEDEALERGUIDEFILE  NATIONALASSIGNEDCODE_VC 1
MAEDEALERGUIDEFILE  NATIONALASSIGNEDNAME_VC 1
MAEDEALERGUIDEFILE  REPLACEDBYDEALERCODE_VC 0
MAEDEALERGUIDEFILE  REPLACINGDEALERCODE_VC  279
MAEDEALERGUIDEFILE  FRANCHISECODES_VC   88
MAEDEALERGUIDEFILE  FRANCHISESCARRIED   7
MAEDEALERGUIDEFILE  FRANCHISESCARRIED4PRINT 7
MAEDEALERGUIDEFILE  CHEVROLET   2
MAEDEALERGUIDEFILE  PBG 2
MAEDEALERGUIDEFILE  CADILLAC    2
MAEDEALERGUIDEFILE  HUMMER  1
MAEDEALERGUIDEFILE  SATURN  1
MAEDEALERGUIDEFILE  SAAB    1
MAEDEALERGUIDEFILE  ISUZU   1
MAEDEALERGUIDEFILE  AREANAME_VC 464
MAEDEALERGUIDEFILE  CITYCODE_VC 3
MAEDEALERGUIDEFILE  MACODE_VC   3
MAEDEALERGUIDEFILE  MANAME_VC   2
MAEDEALERGUIDEFILE  DEALERBACCODE_VC    448
GMSQLDBGMDEALERFILE PK_DEALERCODE_VC    556
GMSQLDBGMDEALERFILE STATUSCODE_VC   3
GMSQLDBGMDEALERFILE STATUSNAME_VC   3
GMSQLDBGMDEALERFILE OPFLAG_VC   2
GMSQLDBGMDEALERFILE BUSFRANCHISEFLAG_VC 0
GMSQLDBGMDEALERFILE LANGUAGE_VC 2
GMSQLDBGMDEALERFILE FRENCHFLAG_VC   0
GMSQLDBGMDEALERFILE DEALERNAME_VC   546
GMSQLDBGMDEALERFILE DEALERNAMESHORT_VC  550
GMSQLDBGMDEALERFILE ADDRESS_VC  469
GMSQLDBGMDEALERFILE POBOX_VC    130
GMSQLDBGMDEALERFILE CITY_VC 426
GMSQLDBGMDEALERFILE PROVINCE_VC 13
GMSQLDBGMDEALERFILE FSALDU_VC   468
GMSQLDBGMDEALERFILE ZONECODE_VC 3
GMSQLDBGMDEALERFILE     ZONENAME_VC 3
GMSQLDBGMDEALERFILE     EWCODE_VC   0
GMSQLDBGMDEALERFILE     EWNAME_VC   0
GMSQLDBGMDEALERFILE     FRANCHISECODES_VC   100
GMSQLDBGMDEALERFILE     CHEVFRANCHISE_BT    2
GMSQLDBGMDEALERFILE     PBGFRANCHISE_BT 2
GMSQLDBGMDEALERFILE     CADFRANCHISE_BT 2
GMSQLDBGMDEALERFILE     HUMFRANCHISE_BT 1
GMSQLDBGMDEALERFILE     SATFRANCHISE_BT 1
GMSQLDBGMDEALERFILE     SAABFRANCHISE_BT    1
GMSQLDBGMDEALERFILE     ISUZUFRANCHISE_BT   1
GMSQLDBGMDEALERFILE     SALESTERRITORYCODE_VC   14
GMSQLDBGMDEALERFILE     GMMACODE_VC 7
GMSQLDBGMDEALERFILE     GMMALEVELCODE_VC    9
GMSQLDBGMDEALERFILE     MMACODE_VC  20
GMSQLDBGMDEALERFILE     MMANAME_VC  20
GMSQLDBGMDEALERFILE     TERMINATIONDATE_D   1
GMSQLDBGMDEALERFILE     REPLACINGDEALERCODE_VC  304
GMSQLDBGMDEALERFILE     REPLACEDBYDEALERCODE_VC 23
GMSQLDBGMDEALERFILE     SERVICETERRITORYCODE_VC 13
GMSQLDBGMDEALERFILE     AREANAME_VC 468
GMSQLDBGMDEALERFILE     CITYCODE_VC 3
GMSQLDBGMDEALERFILE     MACODE_VC   3
GMSQLDBGMDEALERFILE     MANAME_VC   2
GMSQLDBGMDEALERFILE     DEALERBACCODE_VC    486
GMSQLDBDOMESTICGEOGRAPHYDATA    PK_DA_VC    53941
GMSQLDBDOMESTICGEOGRAPHYDATA    FSA_VC  1576
GMSQLDBDOMESTICGEOGRAPHYDATA    FSANAME_VC  588
GMSQLDBDOMESTICGEOGRAPHYDATA    COCMACODE_VC    438
GMSQLDBDOMESTICGEOGRAPHYDATA    COCMANAME_VC    436
GMSQLDBDOMESTICGEOGRAPHYDATA    PBGMACODE_VC    426
GMSQLDBDOMESTICGEOGRAPHYDATA    PBGMANAME_VC    425
GMSQLDBDOMESTICGEOGRAPHYDATA    CADMACODE_VC    126
GMSQLDBDOMESTICGEOGRAPHYDATA    CADMANAME_VC    125
GMSQLDBDOMESTICGEOGRAPHYDATA    HUMMACODE_VC    1
GMSQLDBDOMESTICGEOGRAPHYDATA    HUMMANAME_VC    1
GMSQLDBDOMESTICGEOGRAPHYDATA    MDMACODE_VC 1
GMSQLDBDOMESTICGEOGRAPHYDATA    MDMANAME_VC 1
GMSQLDBDOMESTICGEOGRAPHYDATA    DOMESTICMMACODE_VC  20
GMSQLDBDOMESTICGEOGRAPHYDATA    DOMESTICMMANAME_VC  20
GMSQLDBDOMESTICGEOGRAPHYDATA    PROVINCECODE_VC 12
GMSQLDBDOMESTICGEOGRAPHYDATA    PROVINCENAME_VC 12
GMSQLDBDOMESTICGEOGRAPHYDATA    REPORTTERRITORYCODE_VC  14
GMSQLDBDOMESTICGEOGRAPHYDATA    REPORTTERRITORYNAME_VC  14
GMSQLDBDOMESTICGEOGRAPHYDATA    ZONECODE_VC 3
GMSQLDBDOMESTICGEOGRAPHYDATA    ZONENAME_VC 3
GMSQLDBDOMESTICGEOGRAPHYDATA    GMMACODE_VC 7
GMSQLDBDOMESTICGEOGRAPHYDATA    GMMANAME_VC 7
GMSQLDBDOMESTICGEOGRAPHYDATA    AREACODE_VC 438
GMSQLDBDOMESTICGEOGRAPHYDATA    AREANAME_VC 437
GMSQLDBDOMESTICGEOGRAPHYDATA    ONTARIOSPECIALMARKET_VC 3

一些快速建议-

  • 我看到您在每个连接上都使用修剪。建议尽可能不要这样做,至少对于基于主键的连接,例如-TRIM(a.PK_DA_vc)=TRIM(b.PK_DA_vc),如果不是绝对必要的话。因为,在oracle中,主键在默认情况下具有基于它们的索引。如果在加入时使用函数包装它们,查询优化器将无法在加入时使用基于pk的索引,这将对查询性能产生负面影响

  • 在查询中获得“carIndy-4&..3等”,您不需要每次都重复查询。在select中,只需使用Sum(当(to_NUMBER(to_CHAR(to_date('30-jun-2020'),'yyyyy'))-ReportYear_In)=3,然后在其他0端使用VehicleCount_)作为“carIndy-3”,“carIndy-4”在同一查询中,并在join而不是select中使用此查询。由于这些基本上都是计数,因此此子集将只有一行包含您所需的所有列,因此您应该能够交叉连接它并在主查询的select中获取所有carIndY-n列

  • 另外,将主连接条件放在筛选条件之前,例如在查询中-

    式中((nvl(dlr.ChevFranchise_bt,0)=1 和nvl(dlr.PBGFranchise_bt,0)=0)) 和StatusName_vc='Active' AND TRIM(dlr.PK_DealerCode_vc)=TRIM(gmma.PK_DealerCode_vc)


  • 在这里,第四个and条件是主要的连接条件,应该在where

    中的其他条件之前首先提到它,因为没有索引,所以您可以使用下面的索引尝试下面的查询-

    SELECT dlr.PK_DealerCode_vc,
           dlr.DealerNameShort_vc,
           CASE WHEN mmacode_vc = ''  THEN Province_vc 
                ELSE '' END,
           dlr.AREAName_vc,
           dlr.MMAName_vc,
           gmma.GMMAName_vc,
           ZoneName_vc,
           to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy'),
           NVL(SUM(CASE WHEN (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 4 THEN VehicleCount_in END), 0) "CarIndY - 4",
           NVL(SUM(CASE WHEN (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 3 THEN VehicleCount_in END), 0) "CarIndY - 3"
     FROM DealerFile dlr,
     JOIN (SELECT DISTINCT PK_DealerCode_vc,
                           GMMAName_vc 
             FROM DealerGuideFile) gmma ON TRIM(dlr.PK_DealerCode_vc) = 
     TRIM(gmma.PK_DealerCode_vc)
     JOIN (SELECT COCMACode_vc, VehicleCount_in, ReportYear_in
             FROM VehicleCountByDA b 
             JOIN DomesticGeographyData a ON TRIM(a.PK_DA_vc) = TRIM(b.PK_DA_vc) 
            WHERE gmprimarycode_vc = 'R' 
              AND TRIM(gmcustomweightgroupname_vc) = 'NON-TRUCK') CarIndY ON TRIM(CARINDY.COCMACode_vc) = TRIM(dlr.PK_DealerCode_vc) 
    WHERE nvl(dlr.ChevFranchise_bt, 0) = 1 
      AND nvl(dlr.PBGFranchise_bt, 0) = 0
      AND StatusName_vc = 'Active'
      AND DealerName_vc NOT LIKE '%Study Area%'
      AND DealerName_vc NOT LIKE '%Open Point%'
      AND DealerName_vc NOT LIKE '%Branch%'
      AND LENGTH(RTRIM(dlr.PK_DealerCode_vc)) <= 5;
    

    你的“日期”真的是硬编码字符串吗,还是你只是为了在这里发帖才这样做的?硬编码似乎很不切实际,所以我假设你这样做是为了演示

    此构造在您的选择中

    to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy'),
    
    可以简化为

    to_char(to_date('30-jun-2020','dd-mon-yyyy'),'mmyy')
    

    如果这个日期不是硬编码的,那么几乎可以肯定还有其他机会来改进你对日期的处理,但是我们需要知道你在那里真正使用的是什么


    根据@Somy的建议,简单的编辑将成本降低了4倍:

    SELECT 
    --  DealerCode_vc varchar(6), DealerName_vc varchar(100), province_vc, MAName_vc varchar(25), MMAName_vc varchar(25), GMMAName_vc varchar(25), Zone_vc varchar(25), ReportPeriod_vc varchar(50), 
        dlr.PK_DealerCode_vc, dlr.DealerNameShort_vc, 
        case when mmacode_vc = '' then Province_vc else '' end province_vc, 
        dlr.AREAName_vc, dlr.MMAName_vc, gmma.GMMAName_vc, dlr.ZoneName_vc, 
        to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy') reportperiod_vc
    --  CarIndY-4 int, 
        ,NVL(sum(case when  (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 4  then VehicleCount_in else 0 end ),0) "CarIndY-4" 
    --  CarIndY-3 int, 
        ,NVL(sum(case when  (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 3  then VehicleCount_in else 0 end),0) "CarIndY-3"
    FROM GMSQLDBGMDealerFile dlr,
    (Select distinct PK_DealerCode_vc, GMMAName_vc from MAEDealerGuideFile) gmma,
    GM_TEMP_VehicleCountByDA b,GMSQLDBDomesticGeographyData a
    WHERE trim(dlr.PK_DealerCode_vc) = trim(gmma.PK_DealerCode_vc)
    AND trim(a.COCMACode_vc) = trim(dlr.PK_DealerCode_vc)
    and trim(a.PK_DA_vc) = trim(b.PK_DA_vc) 
    and ((nvl(dlr.ChevFranchise_bt,0) = 1 AND nvl(dlr.PBGFranchise_bt,0)=0)) 
    AND StatusName_vc = 'Active'
    AND DealerName_vc not like ('%Study Area%')
    AND DealerName_vc not like ('%Open Point%')
    AND DealerName_vc not like ('%Branch%')
    AND LENGTH(RTRIM(dlr.PK_DealerCode_vc))<=5
    AND gmprimarycode_vc='R' and trim(gmcustomweightgroupname_vc) = 'NON-TRUCK'
    group by    dlr.PK_DealerCode_vc, dlr.DealerNameShort_vc, 
        case when mmacode_vc = '' then Province_vc else '' end , 
        dlr.AREAName_vc, dlr.MMAName_vc, gmma.GMMAName_vc, dlr.ZoneName_vc, 
        to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy') ;
    
    
    选择
    --DealerCode_vc varchar(6)、DealerName_vc varchar(100)、province_vc、MAName_vc varchar(25)、MMName_vc varchar(25)、GMMAName_vc varchar(25)、Zone_vc varchar(25)、ReportPeriod_vc varchar(50),
    dlr.PK_DealerCode_vc,dlr.DealerNameShort_vc,
    当mmacode_vc=''然后省_vc else''结束省_vc时的情况,
    dlr.AREAName\u vc、dlr.MMAName\u vc、gmma.GMMAName\u vc、dlr.ZoneName\u vc、,
    截止日期(“2020年6月30日”),“mm”)截止日期(“2020年6月30日”),“yy”)报告期
    --卡林迪-4国际酒店,
    ,NVL(当(至编号(至字符(至日期('2020年6月30日'),'yyyy'))-报告年度=4,然后车辆计数在其他0结束时的总和),0)“CarIndY-4”
    --卡林迪-3国际酒店,
    ,NVL(当(至编号(至字符(至日期('2020年6月30日'),'yyyy'))-报告年度=3,然后车辆计数在其他0结束时的总和),0)“CarIndY-3”
    从GMSQLDBGMDealerFile dlr,
    (从MaedalerguiDefile中选择不同的PK_DealerCode_vc、GMMAName_vc)gmma,
    GMU临时车辆计数b、GMSqlDb国内地理数据a
    其中trim(dlr.PK_DealerCode_vc)=trim(gmma.PK_DealerCode_vc)
    AND trim(a.COCMACode_vc)=trim(dlr.PK_DealerCode_vc)
    和修剪(a.PK_DA_vc)=修剪(b.PK_DA_vc)
    和((nvl(dlr.ChevFranchise_bt,0)=1和nvl(dlr.pbgffranchise_bt,0)=0))
    和StatusName_vc='Active'
    和DealName_vc不一样(“%研究区域%”)
    和DealName_vc不一样(“%Open Point%”)
    和DealName_vc不类似(“%Branch%”)
    
    和长度(RTRIM(dlr.PK\u DealerCode\u vc))请始终为性能调整问题共享执行计划。请共享所有索引详细信息。请尝试在问题本身中发布执行计划。每个人(包括我)无法访问google drive。许多网站都会阻止这样的链接。许多论坛参与者拒绝打开这些链接的原因与其他人阻止链接的原因相同。此外,在不了解相关表的结构和数据类型的情况下,不可能分析查询,您需要更新您的问题并发布该表的ddlables。请阅读。这将帮助您理解为什么在您提供更多详细信息之前,我们无法回答此问题,尤其是数据量。非常感谢。您的第二点中提供了所需的所有信息。成本从142k降低到24k。很高兴知道!!非常感谢您的反馈。
    DealerFile - TRIM(PK_DealerCode_vc), TRIM(PK_DealerCode_vc), nvl(ChevFranchise_bt, 0), nvl(PBGFranchise_bt, 0), LENGTH(RTRIM(PK_DealerCode_vc));
    VehicleCountByDA - TRIM(PK_DA_vc);
    DomesticGeographyData - TRIM(PK_DA_vc), TRIM(COCMACode_vc);
    
    to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy'),
    
    to_char(to_date('30-jun-2020','dd-mon-yyyy'),'mmyy')
    
    WHERE (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 4 
    
    SELECT 
    --  DealerCode_vc varchar(6), DealerName_vc varchar(100), province_vc, MAName_vc varchar(25), MMAName_vc varchar(25), GMMAName_vc varchar(25), Zone_vc varchar(25), ReportPeriod_vc varchar(50), 
        dlr.PK_DealerCode_vc, dlr.DealerNameShort_vc, 
        case when mmacode_vc = '' then Province_vc else '' end province_vc, 
        dlr.AREAName_vc, dlr.MMAName_vc, gmma.GMMAName_vc, dlr.ZoneName_vc, 
        to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy') reportperiod_vc
    --  CarIndY-4 int, 
        ,NVL(sum(case when  (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 4  then VehicleCount_in else 0 end ),0) "CarIndY-4" 
    --  CarIndY-3 int, 
        ,NVL(sum(case when  (TO_NUMBER(TO_CHAR(to_date('30-jun-2020'), 'yyyy')) - ReportYear_in) = 3  then VehicleCount_in else 0 end),0) "CarIndY-3"
    FROM GMSQLDBGMDealerFile dlr,
    (Select distinct PK_DealerCode_vc, GMMAName_vc from MAEDealerGuideFile) gmma,
    GM_TEMP_VehicleCountByDA b,GMSQLDBDomesticGeographyData a
    WHERE trim(dlr.PK_DealerCode_vc) = trim(gmma.PK_DealerCode_vc)
    AND trim(a.COCMACode_vc) = trim(dlr.PK_DealerCode_vc)
    and trim(a.PK_DA_vc) = trim(b.PK_DA_vc) 
    and ((nvl(dlr.ChevFranchise_bt,0) = 1 AND nvl(dlr.PBGFranchise_bt,0)=0)) 
    AND StatusName_vc = 'Active'
    AND DealerName_vc not like ('%Study Area%')
    AND DealerName_vc not like ('%Open Point%')
    AND DealerName_vc not like ('%Branch%')
    AND LENGTH(RTRIM(dlr.PK_DealerCode_vc))<=5
    AND gmprimarycode_vc='R' and trim(gmcustomweightgroupname_vc) = 'NON-TRUCK'
    group by    dlr.PK_DealerCode_vc, dlr.DealerNameShort_vc, 
        case when mmacode_vc = '' then Province_vc else '' end , 
        dlr.AREAName_vc, dlr.MMAName_vc, gmma.GMMAName_vc, dlr.ZoneName_vc, 
        to_char(to_date('30-jun-2020'), 'mm') || ' ' || to_char(to_date('30-jun-2020'), 'yy') ;