Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何加速此SQL查询_Sql_Sql Server_Sql Server 2008_Query Optimization - Fatal编程技术网

如何加速此SQL查询

如何加速此SQL查询,sql,sql-server,sql-server-2008,query-optimization,Sql,Sql Server,Sql Server 2008,Query Optimization,首先,感谢您提前提供的任何提示或建议。我不是一个程序员,但我也没有任何其他方式来访问我的数据进行分析,所以我一直在学习(大部分是通过搜索StackOverflow和Google) 因此,下面的查询按预期工作,但速度很慢。我想我有地方可以优化代码,但我已经在拍自己的背,让它工作,所以我的想法。有没有办法加快速度 其基本思想是将预算数据和实际数据作为ID,零表示每个ID的时间(因此这是一个与时间无关的比较),并计算预算与实际累积绩效的比率 编辑:使用SQL Server Management Stu

首先,感谢您提前提供的任何提示或建议。我不是一个程序员,但我也没有任何其他方式来访问我的数据进行分析,所以我一直在学习(大部分是通过搜索StackOverflow和Google)

因此,下面的查询按预期工作,但速度很慢。我想我有地方可以优化代码,但我已经在拍自己的背,让它工作,所以我的想法。有没有办法加快速度

其基本思想是将预算数据和实际数据作为ID,零表示每个ID的时间(因此这是一个与时间无关的比较),并计算预算与实际累积绩效的比率

编辑:使用SQL Server Management Studio 2008 R2,添加了执行计划

注意:表变量仅用于测试代码。满标度代码中使用的永久表

DECLARE @DailyBudget TABLE ( ID varchar(30), D_Date datetime, A float, B float) 
DECLARE @DailyActuals TABLE ( ID varchar(30), D_Date datetime, A float, B float) 

Insert into @DailyActuals (ID, D_Date, A, B) 
Values
('J3PJKFWDBK',  '5/20/2013', 300,1301)
,('J3PJKFWDBK', '5/21/2013', 290,1351)
,('J3PJKFWDBK', '5/23/2013', 283,1320)

Insert into @DailyBudget (ID, D_Date, A, B) 
Values
('J3PJKFWDBK',  '5/1/2013', 263,1401)
,('J3PJKFWDBK', '5/2/2013', 260,1390)
,('J3PJKFWDBK', '5/3/2013', 257,1380)

;WITH Budgets AS
(SELECT ID, D_Date, A, B,
        ROW_NUMBER() OVER(PARTITION BY ID ORDER BY D_DATE ASC) as 'RowNum'  from @DailyBudget where not (A = 0 and B = 0) and D_Date > CONVERT(datetime, '2013-01-01 00:00:00.000', 102)
)
, Actuals AS
(SELECT ID, D_DATE, A, B, 
        ROW_NUMBER() OVER(PARTITION BY ID ORDER BY D_DATE ASC) as 'RowNum'  from @DailyActuals where not (A = 0 and B = 0) and D_Date > CONVERT(datetime, '2013-01-01 00:00:00.000', 102)
)
, BudgetSum AS
(select t1.ID, t1.RowNum, SUM(t2.A) as [A], SUM(t2.B) as [B]
  from Budgets as t1
    inner join Budgets as t2 on t1.RowNum >= t2.RowNum and t1.ID = t2.ID
  group by t1.ID, t1.RowNum, t1.A
)
, ActualSum AS
(select t1.ID, t1.RowNum, SUM(t2.A) as [A], SUM(t2.B) as [B]
  from Actuals as t1
    inner join Actuals as t2 on t1.RowNum >= t2.RowNum and t1.ID = t2.ID
  group by t1.ID, t1.RowNum, t1.A
)
SELECT Budgets.ID, Budgets.D_DATE as [Budget_Date], Actuals.D_DATE as [Actual_Date], 
--A
Budgets.A as [Budget_A], BudgetSum.A as [SumBudget_A], 
Actuals.A as [Actual_A], ActualSum.A as [SumActual_A],
(case BudgetSum.A when 0 then 0 else (ActualSum.A/BudgetSum.A)end) as [A_Ratio],
--B
Budgets.B as [Budget_B], BudgetSum.B as [SumBudget_B], 
Actuals.B as [Actual_B], ActualSum.B as [SumActual_B],
(case BudgetSum.B when 0 then 0 else (ActualSum.B/BudgetSum.B)end) as [B_Ratio]
FROM Budgets 
inner join Actuals on (Actuals.RowNum = Budgets.RowNum and Actuals.ID = Budgets.ID) 
inner join BudgetSum on (Actuals.RowNum = BudgetSum.RowNum and Actuals.ID = BudgetSum.ID)
inner join ActualSum on (Actuals.RowNum = ActualSum.RowNum and Actuals.ID = ActualSum.ID) 
order by Budgets.ID, Budgets.RowNum
SQL Server 2008的执行计划:


有6个表扫描占用了最昂贵查询的18%。这些表扫描都是针对您的表变量
@dailybecast
@DailyActual
。不幸的是,您不能在表变量上创建索引,除非它们是创建唯一索引的副作用,但我怀疑这对您没有帮助


您可以在临时表上创建索引,我建议您尝试将代码转换为使用临时表,创建缺少的索引,看看是否有帮助。创建适当的索引也可能有助于降低排序成本,因为排序成本占YRU最昂贵查询的63%。

如果允许,我建议您设置这些表的一些较小版本,并尝试添加其他索引。每个表可能有10000条记录,ID和D_DATE的值不同,因此可以得到一些有代表性的数据。也许可以创建一个单独的、较小的数据库,让您自由支配

我想你需要一些额外的索引。例如,以下代码按
D_DATE
进行排序(这来自您的预算CTE):

尝试使用相同的列创建第二个非主索引,但顺序为
D_DATE
ID

另一件可能花费很大的事情是生成
RowNum
,然后对其分组,这需要查询引擎按
RowNum
顺序对所有这些记录进行排序。我想试试这样的东西:

 WITH Budgets AS
  (SELECT ID, D_Date, A, B
   from @DailyBudget 
   where not (A = 0 and B = 0) 
   and D_Date > CONVERT(datetime, '2013-01-01 00:00:00.000', 102)
 )
, BudgetSum AS
 (select t1.ID, T1.d_date, SUM(t2.A) as [A], SUM(t2.B) as [B]
  from Budgets as t1
  inner join Budgets as t2 on t1.D_DATE >= t2.D_DATE and t1.ID = t2.ID
 group by t1.ID, T1.D_DATE
)
这几乎是一样的,但它利用了您已有的索引(主键),不需要计算,然后按
RowNum
排序

最后,您使用的按日期获取YTD数据的技术是完全有效的,但是由于您的表有数百万条记录,您所说的可能是要处理的数十亿条合并记录。这并不奇怪,这需要很长时间!考虑使用一些阶段表来保存数据的子集,而不是一次处理每一个记录到最终的数字。或者对查询进行分区(按日期或ID范围),以便可以多次运行更快的查询,并在Excel或一组较小的数据库表中汇编所需的数字,这些表可以随着表的增长使用其他数据进行更新


希望这能有所帮助

编辑您的问题,并粘贴执行计划。如果您包括RDBMS和至少主要版本(例如:SQL Server 2012、Oracle 11i等),也会有所帮助。谢谢。我不知道如何粘贴执行计划,所以我只是链接了它的一张图片(因为我也不能发布图片):
float
如果你想表示金额,它很少是正确的数据类型。如果可以的话,我会改为使用十进制。关于浮点的观点仍然有效:它不应该在大多数业务情况下使用,因为它不精确。如果不切换到十进制,将无法得到想要的结果。Float适用于刻度比精度更重要的情况,或者需要表示非常非常小的数字,不能用十进制来表示。对不起,我应该提到表变量“@DailyBudget”和“@DailyActuals”只是为了测试而使用非机密数据运行查询。这些是实时代码中的永久SQL表。您是在D_日期而不是ID上排序的。我很确定,如果您创建一些额外的索引,您将看到性能改进。嗯,不确定您的确切意思。你的意思不仅仅是表中的属性吗?这两个表都是用以下主键创建的:CONSTRAINT[dailybecudent\u primary\u KEY]主键集群([ID]ASC[D\u DATE]ASC)和[primary]上的(PAD\u INDEX=OFF、STATISTICS\u norecocompute=OFF、IGNORE\u DUP\u KEY=OFF、ALLOW\u ROW\u LOCKS=ON、ALLOW\u PAGE\u LOCKS=ON)和[primary])您需要一个非聚集索引,其中包含您正在排序/筛选的其他列。谢谢!好建议。我有一种感觉,这种缓慢与我正在做的RowNum、排序和加入有关,但不确定正确的方向。我将玩弄索引,并在脑海中进行排序。
 WITH Budgets AS
  (SELECT ID, D_Date, A, B
   from @DailyBudget 
   where not (A = 0 and B = 0) 
   and D_Date > CONVERT(datetime, '2013-01-01 00:00:00.000', 102)
 )
, BudgetSum AS
 (select t1.ID, T1.d_date, SUM(t2.A) as [A], SUM(t2.B) as [B]
  from Budgets as t1
  inner join Budgets as t2 on t1.D_DATE >= t2.D_DATE and t1.ID = t2.ID
 group by t1.ID, T1.D_DATE
)