查询中的慢排序
Posted
技术标签:
【中文标题】查询中的慢排序【英文标题】:Slow sort in query 【发布时间】:2018-12-02 01:02:00 【问题描述】:所以我有这个查询
SELECT
dbo.TQMNCR.NCRID,
dbo.TQMPlantTable.PlantName AS 'Division',
RTRIM(LTRIM(dbo.INVENTTABLE.ITEMGROUPID)) AS 'Item Process/Group',
ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) AS 'Defective Qty',
CASE CATYPE
WHEN 0 THEN
(CASE WHEN dbo.SALESLINE.SALESID = ''
THEN ISNULL((PRICE * (PERCENTEXT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0)
ELSE ISNULL((SALESPRICE * (PERCENTEXT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) END)
WHEN 2 THEN
(CASE WHEN dbo.TQMNCR.SALESID = ''
THEN ISNULL((PRICE * (PERCENTINT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0)
ELSE ISNULL((SALESPRICE * (PERCENTINT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) END)
ELSE 0 END AS 'Total Defective $',
dbo.PRODTABLE.PRODPOOLID
,SCHED.qty,
SUM(salesDollars.sales$) as 'sales Dollars',
fc.YearMonth,
HG.HighLevelItemGroupingCodeName
FROM
dbo.TQMNCR
LEFT OUTER JOIN dbo.TQMDISPOSITION ON dbo.TQMNCR.DISPOSITIONID = dbo.TQMDISPOSITION.DISPOSITIONID
LEFT OUTER JOIN dbo.TQMCA_TABLE ON dbo.TQMCA_TABLE.NCRID = dbo.TQMNCR.NCRID
LEFT OUTER JOIN dbo.TQMNCRDEFECTTYPECODES ON dbo.TQMNCR.NCRID = dbo.TQMNCRDEFECTTYPECODES.NCRID
LEFT OUTER JOIN dbo.TQMPlantTable ON TQMPlantTable.PlantID = dbo.TQMNCR.PlantID
LEFT OUTER JOIN dbo.INVENTTABLE ON dbo.TQMNCR.ITEMID = dbo.INVENTTABLE.ITEMID
LEFT OUTER JOIN dbo.INVENTTABLEMODULE ON dbo.INVENTTABLE.ITEMID = dbo.INVENTTABLEMODULE.ITEMID AND MODULETYPE = 2
LEFT OUTER JOIN dbo.SALESLINE ON dbo.SALESLINE.SALESID = dbo.TQMNCR.SALESID AND dbo.SALESLINE.ITEMID = dbo.TQMNCR.ITEMID
LEFT OUTER JOIN dbo.PRODTABLE ON dbo.TQMNCR.PRODID = dbo.PRODTABLE.PRODID
inner join sched on sched.itemGroup = INVENTTABLE.itemgroupid
inner join salesQty on salesQty.itemGroup = INVENTTABLE.itemgroupid
inner join salesDollars on salesDollars.itemgroup = INVENTTABLE.itemgroupid
LEFT JOIN [MiscReportTables].[dbo].[FiscalCalendar] fc on SCHEDDATE between fc.StartDate and fc.EndDate
left JOIN INVENTITEMGROUP IG on dbo.INVENTTABLE.ITEMGROUPID = IG.ITEMGROUPID
LEFT JOIN Pmf_HighLevelItemGrouping HG on IG.HIGHLEVELITEM = HG.HighLevelItemGroupingCode
WHERE
SCHEDDATE between @start1 and @end1
AND
dbo.TQMNCR.PlantID IN (SELECT [PLANTID]
FROM [Dynamics].[dbo].[TQMPLANTTABLE])
Group By TQMNCR.NCRID,TQMPlantTable.PLANTNAME,INVENTTABLE.ITEMGROUPID,TQMNCRDEFECTTYPECODES.QTY,TQMNCR.CATYPE,SALESLINE.SALESID,INVENTTABLEMODULE.PRICE,
TQMDISPOSITION.PERCENTEXT,INVENTTABLEMODULE.PRICEUNIT,INVENTTABLEMODULE.PRICEUNIT,SALESLINE.SALESPRICE,SALESLINE.PRICEUNIT,TQMNCR.SALESID,TQMDISPOSITION.PERCENTINT,PRODTABLE.PRODPOOLID,
sched.qty,salesQty.salesQTY,fc.YearMonth,HG.HighLevelItemGroupingCodeName`
它运行缓慢,当我查看查询分析器时,我看到了这个
因此,排序(由于 SUM 和相应的 group by 需要)似乎导致此查询运行缓慢。无论如何我可以加快速度吗? group by 非常大,我需要在所有这些表上添加索引吗?
编辑:这是计划的链接:Explain Plan
【问题讨论】:
可以发一下执行计划吗?在这一点上,任何人都无法提供足够的信息来帮助您。 brentozar.com/pastetheplan 我在这里在黑暗中拍摄,但它就在这里。 [动态].[dbo].[TQMPLANTTABLE] 表中的 [PLANTID] 值是否唯一?如果是这样,请使用此表替换您在 dbo.TQMNCR 上执行的过滤,方法是将其从 WHERE 子句中删除并将其添加为连接。 @SeanLange 谢谢,不知道该网站存在。已添加链接 您最后一次更新统计信息是什么时候?您的估计和实际行数存在巨大差异。 我不能说它会解决问题,但差异很大。从估计的行到实际的数量级。这会对如何计算执行计划产生很大的影响。考虑到这些桌子的大小,在下班时间做这件事可能是一个不错的举措。 【参考方案1】:您可以尝试通过子查询(或 CTE)在数十亿行上避免 HUGE GROUP BY
试试这样的:
SELECT
dbo.TQMNCR.NCRID,
dbo.TQMPlantTable.PlantName AS 'Division',
RTRIM(LTRIM(dbo.INVENTTABLE.ITEMGROUPID)) AS 'Item Process/Group',
ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) AS 'Defective Qty',
CASE CATYPE
WHEN 0 THEN
(CASE WHEN dbo.SALESLINE.SALESID = ''
THEN ISNULL((PRICE * (PERCENTEXT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0)
ELSE ISNULL((SALESPRICE * (PERCENTEXT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) END)
WHEN 2 THEN
(CASE WHEN dbo.TQMNCR.SALESID = ''
THEN ISNULL((PRICE * (PERCENTINT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0)
ELSE ISNULL((SALESPRICE * (PERCENTINT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * ISNULL(dbo.TQMNCRDEFECTTYPECODES.QTY,0) END)
ELSE 0 END AS 'Total Defective $',
dbo.PRODTABLE.PRODPOOLID,
SCHED.qty,
salesDollars.[sales Dollars],
fc.YearMonth,
HG.HighLevelItemGroupingCodeName
FROM
dbo.TQMNCR
LEFT OUTER JOIN dbo.TQMDISPOSITION ON dbo.TQMNCR.DISPOSITIONID = dbo.TQMDISPOSITION.DISPOSITIONID
LEFT OUTER JOIN dbo.TQMCA_TABLE ON dbo.TQMCA_TABLE.NCRID = dbo.TQMNCR.NCRID
LEFT OUTER JOIN dbo.TQMNCRDEFECTTYPECODES ON dbo.TQMNCR.NCRID = dbo.TQMNCRDEFECTTYPECODES.NCRID
LEFT OUTER JOIN dbo.TQMPlantTable ON TQMPlantTable.PlantID = dbo.TQMNCR.PlantID
LEFT OUTER JOIN dbo.INVENTTABLE ON dbo.TQMNCR.ITEMID = dbo.INVENTTABLE.ITEMID
LEFT OUTER JOIN dbo.INVENTTABLEMODULE ON dbo.INVENTTABLE.ITEMID = dbo.INVENTTABLEMODULE.ITEMID AND MODULETYPE = 2
LEFT OUTER JOIN dbo.SALESLINE ON dbo.SALESLINE.SALESID = dbo.TQMNCR.SALESID AND dbo.SALESLINE.ITEMID = dbo.TQMNCR.ITEMID
LEFT OUTER JOIN dbo.PRODTABLE ON dbo.TQMNCR.PRODID = dbo.PRODTABLE.PRODID
inner join sched on sched.itemGroup = INVENTTABLE.itemgroupid
inner join salesQty on salesQty.itemGroup = INVENTTABLE.itemgroupid
inner join (
select itemgroup, SUM(sales$) as 'sales Dollars'
from salesDollars
) salesDollars on salesDollars.itemgroup = INVENTTABLE.itemgroupid
LEFT JOIN [MiscReportTables].[dbo].[FiscalCalendar] fc on SCHEDDATE between fc.StartDate and fc.EndDate
left JOIN INVENTITEMGROUP IG on dbo.INVENTTABLE.ITEMGROUPID = IG.ITEMGROUPID
LEFT JOIN Pmf_HighLevelItemGrouping HG on IG.HIGHLEVELITEM = HG.HighLevelItemGroupingCode
WHERE
SCHEDDATE between @start1 and @end1
AND dbo.TQMNCR.PlantID IN (
SELECT [PLANTID]
FROM [Dynamics].[dbo].[TQMPLANTTABLE]
)
【讨论】:
以上是关于查询中的慢排序的主要内容,如果未能解决你的问题,请参考以下文章