nasty slow query | SQL Server Performance Forums

SQL Server Performance Forum – Threads Archive

nasty slow query

Hi,<br /> I have spent the past day and a half rewriting a query from using temporary tables to subqueries and a view in order to speed it up. Sadly, this has not improved performance much and im at a bit of a loss what to try next. Index tuning wizard gives no recommendations, and from examining the indices by hand all suitable ones seem to be in place.<br /><br />The query is this<br /><pre><br /><br />DECLARE @capid int<br />SELECT @capid = 14702<br /><br />select <br />CASE <br />WHEN <br />MAX(ISNULL(parentSet.opt_Type, -1)) &lt; 0<br />THEN<br />– if option type is NULL, get the next chronological option type, which maps to same generic code<br />– if more than one option type exists for the next available date, take the highest precedence<br />ISNULL(<br />(SELECT MAX(opt_type) FROM<br />vw_chappynvd InnerNVD<br />INNER JOIN nvddictionaryoptiongenericlink InnerGL ON (InnerNVD.opt_optioncode = InnerGL.OGL_OptionCode)<br />WHERE<br />– for same cap id<br />opt_id = parentSet.capid and<br />– linked to same generic option<br />OGL_GenericCode = parentSet.dg_genericcode and<br />– takes effect before the date of the option which has been discontinued<br />nvpose_effectivefrom &lt;= parentSet.effectiveFrom and<br /><br />– make sure this option in question has not also been discontinued before this date<br />(<br />select <br />count(X.opt_id)<br />from <br />vw_chappynvd X <br />INNER JOIN nvddictionaryoptiongenericlink NestedGL ON (X.opt_optioncode = NestedGL.OGL_OptionCode)<br />where<br />X.opt_id = InnerNVD.opt_id and<br />X.opt_optioncode = InnerNVD.opt_optioncode and<br />X.opt_type IS NULL and<br />X.nvpose_effectivefrom &lt;= parentSet.effectiveFrom and<br />X.nvpose_effectivefrom &gt;= InnerNVD.nvpose_effectivefrom<br />) = 0<br />)<br />, 0)<br />ELSE<br />MAX(ISNULL(opt_Type, 0))<br />END,<br />effectiveFrom,<br />DG_Description<br />from <br />(<br />select <br />"capid"[email protected],<br />dg_genericcode,<br />"EffectiveFrom"=nvpose_effectivefrom, <br />opt_type<br />from<br />nvddictionarygeneric<br />INNER JOIN nvddictionaryoptiongenericlink ON (ogl_genericcode = DG_GenericCode)<br />LEFT JOIN vw_chappynvd ON (opt_optioncode = ogl_optioncode)<br />where<br />opt_id = @capid<br />———-<br />UNION <br />———-<br />select<br />"capid"[email protected],<br />"DG_GenericCode"=GS_GenericCode,<br />"EffectiveFrom"=GS_EffectiveFrom,<br />"opt_type"=1<br />from <br />NvdGenericStatus<br />where<br />GS_ID = @capid and<br />GS_Status = ‘N’) <br />parentSet<br />INNER JOIN NVDDictionaryGeneric B ON (parentSet.DG_GenericCode = B.DG_GenericCode)<br />group by <br />parentSet.capid,<br />parentSet.dg_genericcode, <br />B.dg_Description, <br />effectivefrom<br />order by<br />B.dg_description, ISNULL(effectivefrom, GETDATE())<br /></pre><br /><br />where the view is defined as <br /><br /><pre><br />CREATE VIEW dbo.vw_chappynvd as <br />– STANDARD START <br />select <br />se_id as opt_id,<br />se_effectivefrom as nvpose_effectivefrom,<br />se_optioncode as opt_optioncode,<br />3 as opt_type<br />from<br />dbo.nvdStandardEquipment<br />UNION<br />– STANDARD END<br />select <br />se_id as opt_id,<br />se_effectiveto as nvpose_effectivefrom,<br />se_optioncode as opt_optioncode,<br />NULL as opt_type<br />from<br />dbo.nvdStandardEquipment<br />where<br />se_effectiveto IS NOT NULL<br />UNION<br />– OPTION START <br />select <br />opt_id,<br />opt_effectivefrom as nvpose_effectivefrom,<br />opt_optioncode,<br />CASE WHEN OPT_Default = 1 THEN 3 ELSE 2 END as opt_type<br />from<br />dbo.nvdOptions <br />UNION<br />– OPTION END<br />select <br />opt_id,<br />opt_effectiveto as nvpose_effectivefrom,<br />opt_optioncode,<br />NULL as opt_type<br />from<br />dbo.nvdOptions <br />where<br />opt_effectiveto IS NOT NULL<br /></pre><br /><br />This results in the following execution plan, which also matches the estimated one<br /><br /><pre><br />StmtText <br />—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————– <br /> |–Sort(ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ /><B>.[DG_Description] ASC, [Expr1093] ASC))<br /> |–Compute Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1092]=If ([Expr1036]&lt;0) then isnull([Expr1090], 0) else [Expr1037], [Expr1093]=isnull([Union1033], getdate())))<br /> |–Nested Loops(Inner Join, WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />IsFalseOrNull([Expr1036]&lt;0))OUTER REFERENCES<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1031], [Union1032], [Union1033]))<br /> |–Stream Aggregate(GROUP BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1031], [Union1032], [Union1033]) DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1036]=MAX(isnull([Union1034], -1)), [Expr1037]=MAX(isnull([Union1034], 0)), <B>.[DG_Description]=ANY(<B>.[DG_Description])))<br /> | |–Sort(ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1031] ASC, [Union1032] ASC, [Union1033] ASC))<br /> | |–Merge Join(Inner Join, MERGE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ /><B>.[DG_GenericCode])=([Union1032]), RESIDUAL<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1032]=<B>.[DG_GenericCode]))<br /> | |–Clustered Index Scan(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDDictionaryGeneric].[PK_NVDDictionary_Generic] AS <B>), ORDERED FORWARD)<br /> | |–Sort(DISTINCT ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1032] ASC, [Union1031] ASC, [Union1033] ASC, [Union1034] ASC))<br /> | |–Concatenation<br /> | |–Hash Match(Inner Join, HASH<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDDictionaryGeneric].[DG_GenericCode])=([NVDDictionaryOptionGenericLink].[ogl_genericcode]))<br /> | | |–Clustered Index Scan(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDDictionaryGeneric].[PK_NVDDictionary_Generic]))<br /> | | |–Nested Loops(Inner Join, OUTER REFERENCES<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1026]) WITH PREFETCH)<br /> | | |–Sort(DISTINCT ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1026] ASC, [Union1024] ASC, [Union1025] ASC, [Union1027] ASC))<br /> | | | |–Concatenation<br /> | | | |–Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[IX_NVDStandardEquipment]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_Id]=[@capid]) ORDERED FORWARD)<br /> | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[PK_NVDStandardEquipment]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_Id]=[@capid]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | | | |–Compute Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1016]=If (Convert([NVDOptions].[OPT_Default])=1) then 3 else 2))<br /> | | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[@capid]) ORDERED FORWARD)<br /> | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[@capid]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDDictionaryOptionGenericLink].[PK_NVDDictionaryOptionGenericLink]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDDictionaryOptionGenericLink].[ogl_optioncode]=[Union1026]) ORDERED FORWARD)<br /> | |–Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDGenericStatus].[idx_id_Status]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDGenericStatus].[GS_Id]=[@capid] AND [NVDGenericStatus].[GS_Status]=’N’) ORDERED FORWARD)<br /> |–Stream Aggregate(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1090]=MAX([Union1062])))<br /> |–Nested Loops(Inner Join, OUTER REFERENCES<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1061]))<br /> |–Filter(WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1088]=0))<br /> | |–Nested Loops(Inner Join, OUTER REFERENCES<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1059], [Union1060], [Union1061]))<br /> | |–Sort(DISTINCT ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1059] ASC, [Union1060] ASC, [Union1061] ASC, [Union1062] ASC))<br /> | | |–Concatenation<br /> | | |–Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[IX_NVDStandardEquipment]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_Id]=[Union1031]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_EffectiveFrom]&lt;=[Union1033]) O RDERED FORWARD)<br /> | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[PK_NVDStandardEquipment]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_Id]=[Union1031]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_EffectiveTo]&lt;=[Union1033] AND [NVDStandardEquipment].[SE_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | | |–Compute Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1051]=If (Convert([NVDOptions].[OPT_Default])=1) then 3 else 2))<br /> | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[Union1031]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_EffectiveFrom]&lt;=[Union1033]) ORDERED FORWARD)<br /> | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[Union1031]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_EffectiveTo]&lt;=[Union1033] AND [NVDOptions].[OPT_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | |–Hash Match(Cache, HASH<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1033], [Union1059], [Union1060], [Union1061]), RESIDUAL<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />(([Union1033]=[Union1033] AND [Union1059]=[Union1059]) AND [Union1060]=[Union1060]) AND [Union1061]=[Union1061]))<br /> | |–Compute Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1088]=Convert([Expr1109])))<br /> | |–Stream Aggregate(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1109]=Count(*)))<br /> | |–Nested Loops(Inner Join)<br /> | |–Sort(DISTINCT ORDER BY<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Union1084] ASC, [Union1085] ASC, [Union1086] ASC, [Union1087] ASC))<br /> | | |–Concatenation<br /> | | |–Filter(WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />3=NULL))<br /> | | | |–Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[IX_NVDStandardEquipment_1]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_OptionCode]=[Union1061] AND [NVDStandardEquipment].[SE_Id]=[Union1059] AND [NVDStandardEquipment].[SE_EffectiveFrom] &gt;= [Union1060] AND [NVDStandardEquipment].[SE_EffectiveFrom] &lt;= [Union1033]) ORDERED FORWARD)<br /> | | |–Filter(WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />NULL=NULL))<br /> | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDStandardEquipment].[PK_NVDStandardEquipment]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDStandardEquipment].[SE_Id]=[Union1059] AND [NVDStandardEquipment].[SE_OptionCode]=[Union1061]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />([NVDStandardEquipment].[SE_EffectiveTo]&gt;=[Union1060] AND [NVDStandardEquipment].[SE_EffectiveTo]&lt;=[Union1033]) AND [NVDStandardEquipment].[SE_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | | |–Filter(WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1076]=NULL))<br /> | | | |–Compute Scalar(DEFINE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[Expr1076]=If (Convert([NVDOptions].[OPT_Default])=1) then 3 else 2))<br /> | | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[Union1059] AND [NVDOptions].[OPT_OptionCode]=[Union1061] AND [NVDOptions].[OPT_EffectiveFrom] &gt;= [Union1060] AND [NVDOptions].[OPT_EffectiveFrom] &lt;= [Union1033]) ORDERED FORWARD)<br /> | | |–Filter(WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />NULL=NULL))<br /> | | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDOptions].[PK_NVDOptions]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NVDOptions].[OPT_Id]=[Union1059] AND [NVDOptions].[OPT_OptionCode]=[Union1061]), WHERE<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />([NVDOptions].[OPT_EffectiveTo]&gt;=[Union1060] AND [NVDOptions].[OPT_EffectiveTo]&lt;=[Union1033]) AND [NVDOptions].[OPT_EffectiveTo]&lt;&gt;NULL) ORDERED FORWARD)<br /> | |–Row Count Spool<br /> | |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDDictionaryOptionGenericLink].[PK_NVDDictionaryOptionGenericLink] AS [NestedGL]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[NestedGL].[ogl_optioncode]=[Union1061]) ORDERED FORWARD)<br /> |–Clustered Index Seek(OBJECT<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[CAR].[dbo].[NVDDictionaryOptionGenericLink].[PK_NVDDictionaryOptionGenericLink] AS [InnerGL]), SEEK<img src=’/community/emoticons/emotion-6.gif’ alt=’:(‘ />[InnerGL].[ogl_optioncode]=[Union1061] AND [InnerGL].[ogl_genericcode]=[Union1032]) ORDERED FORWARD)<br /></pre><br /><br />Now, I dont expect anyone to really understand what im trying to do here, but if anyone can see any obvious areas for improvement based on the execution plan Id love to hear them.<br /><br />Thanks for any time you can spare<br /><br />Chappy<br /><br />
in the view, i am guessing from the apparent logic, that you could use UNION ALL instead of UNION
Can you also get rid of the view, as using the view will make your performance analysis more complex? Is there anyway to work around the NULLs issue? Avoiding using ISNULL is always a good thing? —————————–
Brad M. McGehee, MVP
Webmaster
SQL-Server-Performance.Com
Thanks for the advice guys. Joe, you are right, the union should have been a union all. This shaved a second or so off the query, but still stands at 22 secs. Unfortunately I dont think I can do away with the view, as its used multiple times in the query, and neither the view nor the derived table are suitable for becoming an indexed view. Ill keep plodding on, thanks again
So you now have a union all in both the view and the query? Have you tried to break the query up to see if it is a particular part of the query that is the problem? i.e. split the union into two statements do then run efficiently?
also the statment inside the case statment, how efficient is that by itself?
also how efficient is the who query if you remove the case… (select… and replace it with a constant Cheers
Twan
Okay, still working through all of it, but in one part of the first case statement select you do a subquery summing to zero,rather than that, which has to go through all records in the subquery to get a count to ensure that there have been no discounts, can you do a not exists instead? This will make any records that have results in the subquery perform faster, as it will stop the subquery as soon as the first match is found. Its not much, but I’m starting at the top and working my way down. Chris
]]>