我的查询运行了近2个小时而没有产生任何结果。我已经采取了执行计划,它看起来像下面。
代码
此代码基本上执行数据透视操作:
SELECT y.COMPANYNAME as OIPACOMPANYNAME,
z.POLICYNUMBER as OIPAPOLICYNUMBER,
x.STATUSCODE as OIPASTATUSCODE,
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='PolicyEffDate' THEN w.DATEVALUE
ELSE NULL
END ) as OIPAPOLICYEFFDATE,
x.ISSUESTATECODE as OIPAISSUESTATECODE,
NULL as OIPACURRENTSTATECODE,
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='PolicyEndDate' THEN w.DATEVALUE
ELSE NULL
END ) as OIPAPOLICYENDDATE,
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='IssueAge' THEN w.INTVALUE
ELSE NULL
END) as OIPAISSUEAGE,
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='PolicyYear' THEN w.INTVALUE
ELSE NULL
END) as OIPAPOLICYYEAR,
V.PLANNAME AS OIPAPLANNAME,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='PolicyUniqueIdentifier' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAPOLUPI,
NULL as OIPAPLANMODALFACTOR,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='Participating' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAPARTICIPATING,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='Participating' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAREINSURANCETYPE,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='BaseFaceAmount' THEN w.FLOATVALUE
ELSE NULL
END) as OIPABASEFACEAMOUNT,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='QualType' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAQUALTYPE,
NULL as OIPATAXQUALSALESMARKET, --- field record not found hence set as null
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='BillToDate' THEN w.DATEVALUE
ELSE NULL
END) as OIPABILLTODATE,
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='PaidToDate' THEN w.DATEVALUE
ELSE NULL
END) as OIPAPAIDTODATE,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='PaymentMode' THEN w.TEXTVALUE
ELSE NULL
END ) as OIPAPAYMENTMODE,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='PaymentMethod' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAPAYMENTMETHOD,
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='BillingLeadDays' THEN w.INTVALUE
ELSE NULL
END) as "OIPABILLING LEAD DAYS",
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='BankDraftDay' THEN w.INTVALUE
ELSE NULL
END) as OIPABANKDRAFTDAY,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='EFTDraftCode' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAEFTDRAFTCODE,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='CurrentModalPremiumAmt' THEN w.FLOATVALUE
ELSE NULL
END) as OIPACURRENTMODALPREMIUMAMT,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='CurrentAnnualPremiumAmt' THEN w.FLOATVALUE
ELSE NULL
END) as OIPACURRENTANNUALPREMIUMAMT,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='PolicyModalPremiumAdjustment' THEN w.FLOATVALUE
ELSE NULL
END) as OIPAPOLICYMODALPREMIUMADJ,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='PolicyFee' THEN w.FLOATVALUE
ELSE NULL
END) as OIPAPOLICYFEE,
NULL as OIPALOANPRINCIPAL,
NULL as OIPAOUTSTANDINGLOAN,
NULL as OIPALOANINTERESTDUE,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='LoanInterestRate' THEN w.TEXTVALUE
ELSE NULL
END) as OIPALOANINTERESTRATE,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='LoanInterestType' THEN w.TEXTVALUE
ELSE NULL
END) as OIPALOANINTERESTTYPE,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='APLIndicator' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAAPLINDICATOR,
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='LoanBankDraftDay' THEN w.INTVALUE
ELSE NULL
END) as OIPALOANBANKDRAFTDAY,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='LoanPaymentMethod' THEN w.TEXTVALUE
ELSE NULL
END) as OIPALOANPAYMENTMETHOD,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='LoanPaymentMode' THEN w.TEXTVALUE
ELSE NULL
END) as OIPALOANPAYMENTMODE,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='LoanModalPaymentAmount' THEN w.FLOATVALUE
ELSE NULL
END) as OIPALOANMODALPAYMENTAMOUNT,
MAX(CASE
WHEN w.FIELDTYPECODE='03' AND w.FIELDNAME='LoanBillingLeadDays' THEN w.INTVALUE
ELSE NULL
END) as OIPALOANBILLINGLEADDAYS,
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='LoanBillingDate' THEN w.DATEVALUE
ELSE NULL
END) as OIPALOANBILLINGDATE,
NULL as OIPAPITCASHVALUE,
NULL as OIPAPITCASHSURRVALUE,
NULL as OIPANXTMODVARCASHVALUE,
NULL as OIPAPITDIVONDEP,
NULL as OIPAPITINTONDEP,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='DividendOptionPrimary' THEN w.TEXTVALUE
ELSE NULL
END) as OIPADIVIDENDOPTIONPRIMARY,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='DividendOptionSecondary' THEN w.TEXTVALUE
ELSE NULL
END) as OIPADIVIDENDOPTIONSECONDARY,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendToApplyToCash' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDTOAPPLYTOCASH,
NULL as OIPADIVIDENDTOAPPLYTOACCUDIV,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendToApplyToLoan' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDTOAPPLYTOLOAN,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendToApplyToOYT' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDTOAPPLYTOOYT,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendToApplyToPremium' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDTOAPPLYTOPREMIUM,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendToApplyToPUA' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDTOAPPLYTOPUA,
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='DividendInterestRate' THEN w.FLOATVALUE
ELSE NULL
END) as OIPADIVIDENDINTERESTRATE,
MAX(CASE
WHEN w.FIELDTYPECODE='01' AND w.FIELDNAME='DividendDeclaredDate' THEN w.DATEVALUE
ELSE NULL
END) as OIPADIVIDENDDECLAREDDATE,
NULL as OIPAPUA,
NULL as OIPAPUAPURCHASEDLASTANN,----- field record not found hence set as null
NULL as OIPAOYT,--field record not found hence set as null
NULL as OIPAEICTOAPPLYTOOYT,--- field record not found hence set as null
MAX(CASE
WHEN w.FIELDTYPECODE='04' AND w.FIELDNAME='NetCostBasis' THEN w.FLOATVALUE
ELSE NULL
END) as OIPANETCOSTBASIS,
a.SEGMENTGUID as "OIPASEGMENTGUID",
MAX(CASE
WHEN b.FIELDTYPECODE='02' AND b.FIELDNAME='SegmentFormerSystemPlanCode' THEN b.TEXTVALUE
ELSE NULL
END ) as "OIPASEGMENTFORMERSYSTEMPLAN",
c.SEGMENTNAME as "OIPASEGMENTNAME",
MAX(CASE
WHEN b.FIELDTYPECODE='02' AND b.FIELDNAME='SegmentStatusCode' THEN b.TEXTVALUE
ELSE NULL
END ) as "OIPASEGMENTSTATUSCODE",
MAX(CASE
WHEN b.FIELDTYPECODE='01' AND b.FIELDNAME='SegmentIssueDate' THEN b.DATEVALUE
ELSE NULL
END ) as "OIPASEGMENTISSUEDATE",
MAX(CASE
WHEN b.FIELDTYPECODE='01' AND b.FIELDNAME='SegmentEndDate' THEN b.DATEVALUE
ELSE NULL
END ) as "OIPASEGMENTENDDATE",
MAX(CASE
WHEN b.FIELDTYPECODE='01' AND b.FIELDNAME='SegmentTerminationDate' THEN b.DATEVALUE
ELSE NULL
END ) as OIPASEGMENTTERMINATIONDATE,
MAX(CASE
WHEN b.FIELDTYPECODE='03' AND b.FIELDNAME='SegmentIssueAge' THEN b.INTVALUE
ELSE NULL
END ) as OIPASEGMENTISSUEAGE,
MAX(CASE
WHEN b.FIELDTYPECODE='03' AND b.FIELDNAME='BaseIssueAge' THEN b.INTVALUE
ELSE NULL
END ) as OIPABASEISSUEAGE
FROM ASPOLICY x LEFT JOIN ASCOMPANY y ON (x.COMPANYGUID=y.COMPANYGUID)
INNER JOIN AUDIT_EXT_TEMP_BULK Z ON (z.COMPANYGUID=y.COMPANYGUID and x.POLICYGUID=Z.POLICYGUID )
LEFT JOIN ASPOLICYFIELD w ON (W.POLICYGUID=z.POLICYGUID)
LEFT JOIN ASPLAN v ON (v.PLANGUID=x.PLANGUID AND v.COMPANYGUID=z.COMPANYGUID) -- Plan Information
LEFT JOIN ASSEGMENT a ON (x.POLICYGUID=a.POLICYGUID) -- Segment
LEFT JOIN ASSEGMENTFIELD b ON (b.SEGMENTGUID=a.SEGMENTGUID) -- Segment
LEFT JOIN ASSEGMENTNAME c ON (c.SEGMENTNAMEGUID=a.SEGMENTNAMEGUID)
GROUP BY y.COMPANYNAME,
z.POLICYNUMBER,
x.STATUSCODE,
x.ISSUESTATECODE,
v.PLANNAME,
a.SEGMENTGUID,
c.SEGMENTNAME;
为了便于阅读,以下是声明的尾部:
FROM ASPOLICY x LEFT JOIN ASCOMPANY y ON (x.COMPANYGUID=y.COMPANYGUID)
INNER JOIN AUDIT_EXT_TEMP_BULK Z ON (z.COMPANYGUID=y.COMPANYGUID
and x.POLICYGUID=Z.POLICYGUID )
LEFT JOIN ASPOLICYFIELD w ON (W.POLICYGUID=z.POLICYGUID)
LEFT JOIN ASPLAN v ON (v.PLANGUID=x.PLANGUID
AND v.COMPANYGUID=z.COMPANYGUID) -- Plan Information
LEFT JOIN ASSEGMENT a ON (x.POLICYGUID=a.POLICYGUID) -- Segment
LEFT JOIN ASSEGMENTFIELD b ON (b.SEGMENTGUID=a.SEGMENTGUID) -- Segment
LEFT JOIN ASSEGMENTNAME c ON (c.SEGMENTNAMEGUID=a.SEGMENTNAMEGUID)
GROUP BY y.COMPANYNAME,
z.POLICYNUMBER,
x.STATUSCODE,
x.ISSUESTATECODE,
v.PLANNAME,
a.SEGMENTGUID,
c.SEGMENTNAME;
这些表具有以下索引,其中箭头的左侧表示表,右侧表示具有索引的列。请注意:在运行查询之前,我已通过运行dbms_stats.gather_table_stats('schema','table name');
AUDIT_EXT_TEMP_BULK-->COMPANYGUID,POLICYGUID);
ASPLAN-->PLANGUID
ASPOLICY-->COMPANYGUID
ASCOMPANY-->COMPANYGUID
ASPOLICYFIELD-->POLICYGUID
ASSEGMENT-->POLICYGUID
ASSEGMENTFIELD-->SEGMENTGUID
ASSEGMENTNAME-->SEGMENTNAMEGUID
答案 0 :(得分:3)
“此代码基本上执行数据透视操作”
所以它实际上做的是尝试从an Entity-Attribute-Value model创建一个连贯的结果集。众所周知,这些很难调整。 EAV适合某些用例,例如分析,但是从一组雾化列重新构造一行是非常昂贵的。它们也很难查询(正如您现在所知道的那样!)并且也容易出错,因为重构是一个手动过程 - 这可能不是您需要为OIPAREINSURANCETYPE
返回的内容:
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='Participating' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAPARTICIPATING,
MAX(CASE
WHEN w.FIELDTYPECODE='02' AND w.FIELDNAME='Participating' THEN w.TEXTVALUE
ELSE NULL
END) as OIPAREINSURANCETYPE,
这表明EAV在大多数情况下都不适合使用。模式仍然是固定的,它只是硬编码为读取而不是写入。
当然,对于我们这些必须查询“模型”的人来说,EAV并不难:它还使数据库无法理解数据的存储方式,从而产生糟糕的执行计划。
我承认我印象深刻:我不记得上次在解释计划的G
栏中看到Rows
时。也就是说,您的解释计划显示您的查询正在与 ~923,000,000,000行搏斗,其中GROUP BY
将归结为 ~7,879,000,000行。
那么,考虑到您返回了多少数据,您认为应该花多长时间?
也许最后一个数字让你感到惊讶。毫无疑问,你期待7789行(每个政策一行)。相反,你有一个可怕的笛卡尔积。所有这些额外的行来自哪里?
其中一个问题是AUDIT_EXT_TEMP_BULK
上的联接:每个策略添加超过800行,因为该表上没有过滤器。这是一种检索策略编号的昂贵方法,可能对每个策略都是固定的。如果没有更合理的方法来获取这个值(比如ASPOLICY
表上的一列),用内联视图替换该表应该会减少相当多的数字:
INNER JOIN (select distinct COMPANYGUID, POLICYGUID, POLICYNUMBER
from AUDIT_EXT_TEMP_BULK Z )
ON (z.COMPANYGUID=y.COMPANYGUID and x.POLICYGUID=Z.POLICYGUID )
另一件事是GROUP BY
:您实际上只需聚合这些列:
y.COMPANYNAME as OIPACOMPANYNAME,
z.POLICYNUMBER as OIPAPOLICYNUMBER,
x.STATUSCODE as OIPASTATUSCODE
删除其他列可能会大大改善解释计划。