这是我开始说我不是开发人员的地方,这不是我的代码。作为DBA,尽管它从性能角度出现在板上。执行计划向我显示,Table2的CI扫描别名为D,Table2别名为E.关注表2别名为E.扫描来自E.SEQ_NBR =的where子句中的子查询 我也看到了比需要更多的处决。我知道它取决于表格上的确切索引结构,但在很高的层次上,我所看到的可能是它发现的每个匹配的聚合(min)导致的CI扫描。基本上它是在EMPLID和其他领域的每个匹配的最小SEQ_NBR的桌子上走?
如果可能的话,是否更多地是由于它的编写方式(我认为将CTE与一些ROW_NUMBER逻辑结合起来会有所帮助)或缺乏索引?我试图避免抛出一个索引“只是因为”。我在where子句中挂起了那个子查询。
SELECT
D.EMPLID
,D.JOBCODE
,D.DEPTID
,E.DUR
,SUM(D.TL_QUANTITY) 'YTD_TL_QUANTITY'
FROM
Table1 B
,Table2 D
,Table2 E
WHERE
D.TRC = B.TRC
AND B.TL_ERNCD IN ( @0, @1, @2, @3, @4, @5, @6 )
AND D.EMPLID = E.EMPLID
AND D.EMPL_RCD = E.EMPL_RCD
AND D.DUR < = E.DUR
AND D.DUR > = '1/1/' + CAST(DATEPART(YEAR, E.DUR) AS CHAR)
AND E.SEQ_NBR =
( SELECT
MIN(EX.SEQ_NBR)
FROM
Table2 EX
WHERE
E.EMPLID = EX.EMPLID
AND E.EMPL_RCD = EX.EMPL_RCD
AND E.DUR = EX.DUR
)
AND B.EFFDT = ( SELECT
MAX(B_ED.EFFDT)
FROM
Table1 B_ED
WHERE
B.TRC = B_ED.TRC
AND B_ED.EFFDT < = GETDATE()
)
GROUP BY
D.EMPLID
,D.JOBCODE
,D.DEPTID
,E.DUR
答案 0 :(得分:1)
MIN操作与CL扫描无关。使用排序计算MIN或Max。问题很可能是子查询执行的次数。它必须遍历父查询中返回的每个记录的子查询。 CTE在这里可能会有所帮助,具体取决于Table2的大小,但我认为你不必担心找到MIN()的替代品......至少还没有。
答案 1 :(得分:1)
相关子查询是性能杀手。删除它们并用CTE和JOIN或派生表替换它们。
尝试这样的事情(未经测试)
SELECT
D.EMPLID
,D.JOBCODE
,D.DEPTID
,E.DUR
,SUM(D.TL_QUANTITY) 'YTD_TL_QUANTITY'
FROM Table1 B
JOIN Table2 D
ON D.TRC = B.TRC AND D.EMPLID = E.EMPLID
JOIN Table2 E
ON D.EMPL_RCD = E.EMPL_RCD AND D.DUR < = E.DUR
JOIN (SELECT MIN(EX.SEQ_NBR)FROM Table2) EX
ON E.EMPLID = EX.EMPLID
AND E.EMPL_RCD = EX.EMPL_RCD
AND E.DUR = EX.DUR
JOIN (SELECT MAX(B_ED.EFFDT)
FROM Table1
WHERE B_ED.EFFDT < = GETDATE()) B_ED
ON B.TRC = B_ED.TRC
WHERE B.TL_ERNCD IN ( @0, @1, @2, @3, @4, @5, @6 )
AND D.DUR > = '1/1/' + CAST(DATEPART(YEAR, E.DUR) AS CHAR)
就隐式连接语法而言,不允许任何人再次执行此操作。这是一种糟糕的编程技术。作为DBA,您可以说出您将在数据库中使用和不允许的内容。代码审查了什么,并且在它们删除隐式语法之前不会传递它。
为什么不好?首先,你会偶然发生交叉连接。此外,从维护的角度来看,您无法判断交叉连接是偶然的(因此查询不正确)还是故意的。这意味着在其中具有交叉连接的查询是不可维护的。
接下来,如果您必须稍后将某些连接更改为外连接并且不同时修复所有连接,则可能会得到不正确的结果(没有经验的开发人员可能会注意到这一点。在SQL Server中2008年你不能使用隐式语法进行外部联接,但它甚至不应该像SQl Server 2000那样被使用,因为联机丛书(对于SQL Server 2000)表明存在被误解的情况。换句话说。外部联接的语法不可靠。使用隐式联接没有任何借口,使用显式联接你不会从中获得任何东西,它们可以产生更多问题。
您需要教育您的开发人员并告诉他们这段代码(自1992年以来已经过时!)不再可接受。
答案 2 :(得分:0)
这是一个快速的,但是这个,CAST('1/1 /'+ CAST(DATEPART(YEAR,E.DUR)AS CHAR)AS DATETIME),它可能导致Table2 E上的表扫描,因为该功能很可能必须针对每一行进行评估。