Sql server SQL查询由于日期函数而运行缓慢

Sql server SQL查询由于日期函数而运行缓慢,sql-server,common-table-expression,query-performance,Sql Server,Common Table Expression,Query Performance,我正在使用ManagementStudio 18对SQLServer数据库运行一个查询,在服务器上运行需要3-4分钟。如果我删除dates函数,它将在1分钟内在我的机器上运行,但我需要dates函数。有人能帮忙吗?提前谢谢你 以下是在服务器上执行3-4的原始查询: With A AS ( Select DSS.transactionSynchronizationId, DSS.transactionDate, DSS.transactionTime,

我正在使用ManagementStudio 18对SQLServer数据库运行一个查询,在服务器上运行需要3-4分钟。如果我删除dates函数,它将在1分钟内在我的机器上运行,但我需要dates函数。有人能帮忙吗?提前谢谢你

以下是在服务器上执行3-4的原始查询:

With A AS 
(
Select          DSS.transactionSynchronizationId, DSS.transactionDate, DSS.transactionTime,
                convert (varchar, CAST(DateAdd(minute, DateDiff(minute, 0, DSS.transactionTime), 0) AS smalldatetime), 24) As DSS_TransactionTime_EST, DSS.processedBy, 
                DSS.transactionType, DSS.country, DSS.state, DSS.partner,
                DSS.originUnitPrice, DSS.discount, DSS.taxAmount, 
                Case When transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then (DSS.taxAmount*-1) Else DSS.taxAmount End As DSS_Tax_Amount,
                Case When DSS.country In ('US', 'PR', 'CA') And transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then -DSS.originUnitPrice - DSS.discount 
                When DSS.country In ('US', 'PR', 'CA') And transactionType Not In ('REFUND', 'CHARGEBACK', 'CREDIT') Then DSS.originUnitPrice - DSS.discount
                When DSS.country Not In ('US', 'PR', 'CA') And transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then (-DSS.originUnitPrice - DSS.discount - DSS.taxAmount)
                Else DSS.originUnitPrice - DSS.discount - DSS.taxAmount End AS DSS_Gross_Sales
From TableA As DSS
),
C As
(
Select Distinct VTX.[Transaction Synchronization ID], VTX.[Transaction Process Date], VTX.[Transaction Process Time],
                convert(varchar, DATEADD (HOUR , -5 , [Transaction Process Time]) , 24) As Vertex_TransactionTime_EST, VTX.[Situs Country Code 2], VTX.[Situs Main Division],
                VTX.[Taxpayer Division Code], VTX.[Gross Amount] As VTX_Gross_Amount, Sum (VTX.[Tax Amount]) As VTX_Tax_Amount 
From TableB As VTX

Group By VTX.[Transaction Synchronization ID], VTX.[Transaction Process Date], VTX.[Transaction Process Time], VTX.[Situs Country Code 2], VTX.[Situs Main Division],
                VTX.[Taxpayer Division Code], VTX.[Gross Amount]
),
B As
(
Select          C.[Transaction Synchronization ID], C.[Transaction Process Date], C.[Transaction Process Time],
                convert(varchar, DATEADD (HOUR , -5 , C.[Transaction Process Time]) , 24) As Vertex_TransactionTime_EST, C.[Situs Country Code 2], C.[Situs Main Division],
                C.[Taxpayer Division Code], Sum (C.VTX_Gross_Amount) As VTX_Gross_Amount, Sum (C.VTX_Tax_Amount) As VTX_Tax_Amount 
From C

Group By C.[Transaction Synchronization ID], C.[Transaction Process Date], C.[Transaction Process Time],
                convert(varchar, DATEADD (HOUR , -5 , C.[Transaction Process Time]) , 24), C.[Situs Country Code 2], C.[Situs Main Division],
                C.[Taxpayer Division Code]
)
Select          A.transactionSynchronizationId, B.[Transaction Process Date], B.Vertex_TransactionTime_EST, A.transactionDate, A.DSS_TransactionTime_EST, A.processedBy, A.transactionType,
                B.[Situs Country Code 2], A.country, B.[Situs Main Division], A.state, A.partner, B.[Taxpayer Division Code], B.VTX_Gross_Amount, B.VTX_Tax_Amount, A.originUnitPrice,
                A.discount, A.DSS_Tax_Amount, A.DSS_Gross_Sales, Cast ((A.DSS_Gross_Sales - B.VTX_Gross_Amount) As decimal (10,2)) As 'Gross Sales Diff', 
                A.DSS_Tax_Amount, Cast (A.DSS_Tax_Amount - B.VTX_Tax_Amount As decimal (10,2)) As 'Tax Diff'
From A Join B
On A.transactionSynchronizationId = B.[Transaction Synchronization ID]
以下是运行速度更快的查询:

With A AS 
(
Select          DSS.transactionSynchronizationId, DSS.transactionDate, DSS.transactionTime,
                convert (varchar, CAST(DateAdd(minute, DateDiff(minute, 0, DSS.transactionTime), 0) AS smalldatetime), 24) As DSS_TransactionTime_EST, DSS.processedBy, 
                DSS.transactionType, DSS.country, DSS.state, DSS.partner,
                DSS.originUnitPrice, DSS.discount, DSS.taxAmount, 
                Case When transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then (DSS.taxAmount*-1) Else DSS.taxAmount End As DSS_Tax_Amount,
                Case When DSS.country In ('US', 'PR', 'CA') And transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then -DSS.originUnitPrice - DSS.discount 
                When DSS.country In ('US', 'PR', 'CA') And transactionType Not In ('REFUND', 'CHARGEBACK', 'CREDIT') Then DSS.originUnitPrice - DSS.discount
                When DSS.country Not In ('US', 'PR', 'CA') And transactionType In ('REFUND', 'CHARGEBACK', 'CREDIT') Then (-DSS.originUnitPrice - DSS.discount - DSS.taxAmount)
                Else DSS.originUnitPrice - DSS.discount - DSS.taxAmount End AS DSS_Gross_Sales
From TableA As DSS
),
C As
(
Select Distinct VTX.[Transaction Synchronization ID], VTX.[Transaction Process Date], VTX.[Transaction Process Time],
                convert(varchar, DATEADD (HOUR , -5 , [Transaction Process Time]) , 24) As Vertex_TransactionTime_EST, VTX.[Situs Country Code 2], VTX.[Situs Main Division],
                VTX.[Taxpayer Division Code], VTX.[Gross Amount] As VTX_Gross_Amount, Sum (VTX.[Tax Amount]) As VTX_Tax_Amount 
From TableB As VTX

Group By VTX.[Transaction Synchronization ID], VTX.[Transaction Process Date], VTX.[Transaction Process Time], VTX.[Situs Country Code 2], VTX.[Situs Main Division],
                VTX.[Taxpayer Division Code], VTX.[Gross Amount]
),
B As
(
Select          C.[Transaction Synchronization ID], C.[Transaction Process Date], C.[Transaction Process Time],
                 C.[Situs Country Code 2], C.[Situs Main Division],
                C.[Taxpayer Division Code], Sum (C.VTX_Gross_Amount) As VTX_Gross_Amount, Sum (C.VTX_Tax_Amount) As VTX_Tax_Amount 
From C

Group By C.[Transaction Synchronization ID], C.[Transaction Process Date], C.[Transaction Process Time],
                  C.[Situs Country Code 2], C.[Situs Main Division],
                C.[Taxpayer Division Code]
)
Select          A.transactionSynchronizationId, B.[Transaction Process Date], A.transactionDate, A.DSS_TransactionTime_EST, A.processedBy, A.transactionType,
                B.[Situs Country Code 2], A.country, B.[Situs Main Division], A.state, A.partner, B.[Taxpayer Division Code], B.VTX_Gross_Amount, B.VTX_Tax_Amount, A.originUnitPrice,
                A.discount, A.DSS_Tax_Amount, A.DSS_Gross_Sales, 
                A.DSS_Tax_Amount, Cast (A.DSS_Tax_Amount - B.VTX_Tax_Amount As decimal (10,2)) As 'Tax Diff'
From A Join B
On A.transactionSynchronizationId = B.[Transaction Synchronization ID]
应采取的措施:

  • 简化你的疑问,肯定有办法吗?似乎存在聚合冗余
  • 运行执行计划,找出瓶颈所在
  • 尝试分别运行每个块,您可能会发现其中一个块比其他块花费的时间要多得多
  • 显示表结构,包括索引和一些示例数据,查询优化器可能无法利用该查询的索引
  • 改进命名约定:表名别名(如A、B、C)没有意义,它们代表什么还不清楚,混淆的风险更高
  • 如果查询是存储过程的一部分:

    • 有时您可以使用变量而不是复杂的表达式(对于只需要计算一次的值)
    • 使用临时表,并分多个步骤填充它们-尝试生成单个CTE可能会导致性能降低
  • 也许你也可以用
    WHERE
    子句过滤出源表,在不知道数据和目的的情况下很难判断,但我的印象是你正在提取所有数据,然后对其进行聚合

是的,这对我们来说很难理解,也许对你也是

我的直接建议是从第一个构建块开始,确保您的查询得到优化,尽可能使用索引,并且不会获取超过需要的数据。始终关注执行计划。如有必要,添加索引,例如按日期范围搜索的日期。即使是一分钟也不能接受响应时间。这只会随着数据集的增长而增加

现在,如果你认为问题来自以下陈述:

convert(varchar, DATEADD (HOUR , -5 , C.[Transaction Process Time]) , 24) As Vertex_TransactionTime_EST,
如果您真的必须这样做,也许可以尝试不同的形式,摆脱varchar转换。您只返回带有时区偏移的
HH:mm:ss


说到这里,我想我应该提到SQL Server有时区函数,例如,或者-很高兴知道它们的存在。

这些查询非常难以阅读。也许可以尝试删除与问题无关的部分,并为我们提供一个更简单的查询。但是,如果您不需要CTE中的日期函数作为join/where子句,请将它们拉到返回实际数据的select语句中。它正在运行哪个版本的SQL Server?您希望从
B
中得到哪些不需要从
C
中得到的内容
B
聚合
C
的列,添加一个额外的列,该列的日期计算将
[Transaction Process Time]
获取到最接近的秒数,但行仍然由
[Transaction Process Time]
聚合,因此
总和将仍然相同。。。