Sql 使用数千万条记录和左连接优化Select查询

Sql 使用数千万条记录和左连接优化Select查询,sql,sql-server,tsql,Sql,Sql Server,Tsql,我试图打破下面的查询从过去的3天,但无法修改它在所有作为分组的条款是在那里结束。查询在1小时内执行,返回30K条记录,表a包含数千万条记录。所有表的索引都已就绪。下面是屏蔽查询: DECLARE @Variable1 VARCHAR(6) = '199101' SELECT A.Col1, 'A' as Col2_Name, A.Col3, B.Col_05, A.Col4, C.C

我试图打破下面的查询从过去的3天,但无法修改它在所有作为分组的条款是在那里结束。查询在1小时内执行,返回30K条记录,表a包含数千万条记录。所有表的索引都已就绪。下面是屏蔽查询:

DECLARE @Variable1 VARCHAR(6) = '199101' 

SELECT        
A.Col1,          
'A' as Col2_Name,          
A.Col3,         
B.Col_05,        
A.Col4,          
C.Col_01 AS Col_01_Name,         
SUBSTRING(A.Col5,1,4) AS Col5_Name,          
D.Col_12,     
A.Col6 AS Col6,       
A.Col7,          
SUBSTRING(A.Col8,1,4) AS Col8_Name,          
A.Col9,          
E.Col_01,     
@Variable1 as 'ACC_FROM'          
,@Variable1 AS 'ACC_TO'          
,'' AS [Start_DATE],           
'' AS [End_DATE],         
@Variable1 AS 'PERIOD',          
@Variable1 as Var_Name,          
A.Col10,       
A.Col11,       
SUM(A.Col12) AS 'A1',          
0 AS 'B1',          
0 AS 'C1',          
0 AS 'D1',          
0 AS 'E1',          
0 AS 'F1',          
SUM(A.Col12) AS 'TOTAL'   

FROM TableA A         
LEFT JOIN TableB B ON A.Col3 = B.Col_3 and B.Col_11=A.Col11 AND B.Col_13=A.Col13 AND A.Col1 = B.Col1 and A.Col7 = B.Col_7
LEFT JOIN TableC C ON A.Col4 = LTRIM(RTRIM(C.Col_04))           
LEFT JOIN TableD D ON SUBSTRING(A.Col5,1,4) = SUBSTRING(D.Col_05,1,4) and A.Col1 = D.Col_01 and A.Col7 = D.Col_07          
LEFT JOIN TableE E ON A.Col9 = E.Col_09   

WHERE A.Col14 = 2          
AND A.Col15 = 'C'          
AND A.Col16 <= @Variable1    

GROUP BY           
A.Col1,          
A.Col3,          
B.Col_05,         
A.Col4,          
C.Col_01,         
SUBSTRING(A.Col5,1,4),          
D.Col_12,       
A.Col6,
A.Col7,          
SUBSTRING(A.Col8,1,4),          
A.Col9,          
E.Col_01,  
A.Col10,    
A.Col11

HAVING SUM(A.Col12)<>0  
DECLARE@Variable1 VARCHAR(6)='199101'
挑选
A.Col1,
“A”作为Col2_名称,
A.Col3,
B.Col_05,
A.Col4,
C.Col_01作为Col_01_名称,
子字符串(A.Col5,1,4)作为Col5_名称,
D.Col_12,
A.Col6作为Col6,
A.Col7,
子字符串(A.Col8,1,4)作为Col8_名称,
A.Col9,
E.Col_01,
@变量1为“ACC_FROM”
,@变量1为“ACC_TO”
,“”作为[开始日期],
“”作为[结束日期],
@变量1作为“期间”,
@变量1作为变量名,
A.Col10,
A.Col11,
总和(A.Col12)为“A1”,
0作为“B1”,
0作为“C1”,
0作为“D1”,
0作为“E1”,
0作为“F1”,
合计(A.Col12)为“总计”
从表A
左键连接A.Col3=B.Col_3和B.Col_11=A.Col11和B.Col_13=A.Col13和A.Col1=B.Col1和A.Col7=B.colu 7上的表B
A.Col4=LTRIM(RTRIM(C.Col_04))上的左连接表C
子串(A.Col5,1,4)=子串(D.Col_05,1,4)和A.Col1=D.Col_01和A.Col7=D.Col_07上的左联接表D
A.Col9=E.Col_09上的左连接表E
其中A.Col14=2
和A.Col15='C'

还有A.Col16你收到了不少评论和很好的建议。我将更详细地介绍其中一些

执行计划 如果您通常被限制为只读用户(就像我在组织中一样),那么获取查询执行计划(并理解它们!)可能会很困难。要解决权限级别问题,最简单的方法是获取数据库的副本,并将其安装到您拥有完全权限的本地计算机上。在那里,您可以调整查询并尝试不同的方法。在您的计算机上保留一份数据库副本(我可能会补充说,保持它们的安全性)将允许您消除可能以不一致的方式影响查询性能的任何网络问题的影响

搜索参数 其中一条评论提到了非SARGable谓词。你可以找到更多关于这些的信息。您不会相信遵循本文的指导原则会对查询的性能产生影响

索引 在索引方面,您说过所有适当的索引都已准备就绪。如果这是真的,并且你知道你的索引没有比它们更好的了,那么忽略这一段的其余部分。如果你不能100%确定你需要的所有东西都在那里,那就看看吧,因为它有一些非常枯燥但有用的索引信息关于同一主题,It’读起来容易一点(但不够全面)

具体建议 查看您的查询,您正在根据表达式的结果进行分组并加入其中。这样做可能会很费劲,尤其是当涉及数百万条记录时。在这种情况下,最好先过滤掉尽可能多的不需要的记录,然后再开始应用需要大量处理能力的更具体的过滤器。修复?使用一些简单的联接,并在临时表中使用这些联接,以一组较小的记录开始筛选。在临时表中,还可以创建表示分组和联接语句中使用的这些表达式的结果的字段。例如,可以在临时表中有col_04的修剪副本(即col_04_trimmed)以及Col5的前四个字符(Col5_first_4)。临时表的构建需要更多的前期处理,但是一旦构建了临时表,您通常可以查询和处理临时表的内容,这要比动态处理大量数据快得多。完成查询后,放下临时表,开始您的业务

此外,当您有一个始终表示数字的变量时,请将其存储为数字(整数、浮点等)变量。这将节省一些隐式转换的时间,特别是在数百万行之间

最后,你说

Having SUM(A.Col12)<>0

我希望这有帮助

发布查询计划的屏幕截图。在每个表的每个索引中,哪些列被索引?用您正在使用的数据库标记您的问题。毫不奇怪,这是如此缓慢。联接中有许多不可争论的谓词,这将导致全表扫描。请告诉我这些不是你真正的列名。如果没有表定义和索引定义,任何人都无法提供帮助。我经常听到“索引已就位”,但在检查时,索引不是查询所需的。仅仅在列上抛出索引并不能加快查询速度。它需要注意细节。
在A.Col4=LTRIM(RTRIM(C.Col_04))上表示您需要清理表格。空白填充不应该出现在数据中,尤其是当它们是您要加入的关键字段时<子字符串(A.Col5,1,4)上的代码>表示子字符串(D.Col_05,1,4)
表示数据库设计不佳。它表明你已经打破了第一个正常形式。这样做的主要后果是表现不佳。这个答案(太棒了)早就应该受到人们的喜爱了+1.
Having SUM(A.Col12) > 0