【问题标题】:Hash Match (Inner Join) cost 50% in my query哈希匹配(内部连接)在我的查询中花费 50%
【发布时间】:2018-05-11 03:56:32
【问题描述】:

我还没有与Hash Join 互动过。 根据下图,我需要在表 tblFin_Invoices 上建立索引吗?

或者我需要为哪个表创建索引以避免这种哈希连接?

我可以做些什么来缓解查询吗?

----------------------------------------------- -------------------------

declare  
        @EffDateFrom datetime = '2017-02-01',  
        @EffDateTo  datetime= '2017-12-31'

DECLARE @ValidInvoicesTable TABLE (InvoiceNum INT PRIMARY KEY)   
INSERT INTO @ValidInvoicesTable
SELECT DISTINCT INV.InvoiceNum
FROM            tblFin_Invoices INV
    INNER JOIN      tblQuotes ON INV.QuoteID = tblQuotes.QuoteID
    --INNER JOIN        tblClientOffices ON tblQuotes.QuotingLocationGuid = tblClientOffices.OfficeGUID 
WHERE           (INV.Failed = 0) 

                AND dateDiff(d, @EffDateFrom, dbo.tblQuotes.EffectiveDate) >= 0 
                AND dateDiff(d, @EffDateTo, dbo.tblQuotes.EffectiveDate) <= 0 
                AND dbo.tblQuotes.LineGUID = '6E00868B-FFC3-4CA0-876F-CC258F1ED22D'  

DECLARE @TempData TABLE(
    [QuoteID] int,
    [QuoteGUID] [uniqueidentifier] NOT NULL,
    [CompanyLocationGuid] [uniqueidentifier] NULL,
    [UnderwriterUserGuid] [uniqueidentifier] NULL,
    [InsuredGuid] [uniqueidentifier] NULL,
    [ProducerGuid] [uniqueidentifier] NULL,
    [ProducerContactGuid] [uniqueidentifier] NULL,
    [EffectiveDate] datetime NULL,
    --[InvoiceDate] datetime NULL,
    [AccountingDate] datetime NULL,
    [PolicyTypeID] tinyint NOT NULL,  --------------
    [TransactionTypeID] varchar(2)  NULL,  
    [QuoteStatusID] tinyint NOT NULL,
    [PolicyNumber] [varchar](150) NULL,
    [StateID] [char](2) NULL,
    [Premium] [money] NULL,
    BondRate decimal (5,4) NULL,
    [PenalLiability] [money] NULL,
    [CompanyCommission] decimal(3,2) NULL
)

    INSERT INTO @TempData
    SELECT      
                INV.QuoteID,
                tblQuotes.QuoteGUID,
                tblQuotes.CompanyLocationGuid,
                tblQuotes.UnderwriterUserGuid,
                tblSubmissionGroup.InsuredGuid,
                tblProducerLocations.ProducerGUID,
                tblQuotes.ProducerContactGuid,
                INV.EffectiveDate,
                INV.InvoiceDate,
                --dbo.CalcAccountingDate(tblQuotes.QuoteStatusID,INV.invoicedate,INV.effectivedate, tblQuotes.EndorsementEffective) AccountingDate,
                tblQuotes.PolicyTypeID,
                tblQuotes.TransactionTypeID, 
                tblQuotes.QuoteStatusID,
                tblQuotes.PolicyNumber,         
                tblQuotes.StateID, 
                (SELECT ISNULL(SUM(tblFin_InvoiceDetails.AmtBilled), 0)
                 FROM tblFin_InvoiceDetails
                 WHERE (tblFin_InvoiceDetails.ChargeType = 'P')
                 AND (tblFin_InvoiceDetails.InvoiceNum = INV.InvoiceNum))
                 AS Premium,
                 [Dynamic_Data_SuretyPRC].BondRate,
                 [Dynamic_Data_SuretyPRC].BondAmount,
                 [Dynamic_Data_SuretyPRC].CompanyComm   

    FROM            tblFin_Invoices INV
    INNER JOIN      tblQuotes ON INV.QuoteID = tblQuotes.QuoteID
    INNER JOIN      tblProducerLocations ON INV.ProducerLocationGUID = tblProducerLocations.ProducerLocationGUID  
    INNER JOIN      tblSubmissionGroup ON tblQuotes.SubmissionGroupGuid = tblSubmissionGroup.SubmissionGroupGUID 
    LEFT  JOIN      [dbo].[Dynamic_Data_SuretyPRC] ON Dynamic_Data_SuretyPRC.QuoteGUID = tblQuotes.QuoteGUID 
    WHERE       INV.InvoiceNum IN (SELECT * FROM @ValidInvoicesTable)           
    ORDER BY    INV.InvoiceDate
--select * from @TempData

【问题讨论】:

  • 老实说,我认为您需要进一步回顾您的查询。填充该表变量具有多个 nonSARGable 谓词。更糟糕的是,您根本不需要此处发布的代码中的 table 变量。您可以删除该表变量并重新编写谓词,以使列不在函数内。
  • 谢谢肖恩。你认为我应该放弃哪张桌子?第一个 (@ValidInvoicesTable) 或第二个 (@TempData)。我创建第一个 (@ValidInvoicesTable) 的原因是出于性能目的。如果我使用WHERE INV.InvoiceNum IN (SELECT * FROM @ValidInvoicesTable) - 查询运行得更快。
  • 我可能会放弃他们两个。我什至没有注意到你正在使用其中的两个。我认为您希望所有具有有效日期的行都在两个日期参数之间?不太确定你在那里做什么。但这可以在没有所有表变量的情况下在单个 select 语句中完成(根据行数,这可能成为它们自己的性能瓶颈)。
  • 如果查询中的大部分时间都花在优化操作上,即进行索引查找和哈希匹配,那么这是优化的。如果是扫描,我会担心的。这是一个误报,我同意@SeanLange 在这里您需要查看表变量和结构。查询很难阅读,也很难执行。

标签: sql-server tsql indexing sql-server-2012


【解决方案1】:

您在@ValidInvoicesTable 的第一个查询中使用的所有表也在第二个查询中。不要使用 @ValidInvoicesTable,而是使用该 SELECT 中的 WHERE 条件并替换第二个 SELECT 语句中的 WHERE 条件。

如果 DateTime 字段实际上包含时间,我还将使用 BETWEEN 而不是两个语句进行日期比较,以获得相同的结果,您需要 CAST/CONVERT the EffectiveDate。

我也会从 tblFin_InvoiceDetails 中加入。

我假设您打算将@TempData 表用于其他的东西,而不仅仅是一个 SELECT 语句。如果我错了,您应该完全删除关于 @TempData 表的 DECLARE 和 INSERT INTO。

以下是我的建议。

declare  
     @EffDateFrom datetime = '2017-02-01',  
     @EffDateTo  datetime= '2017-12-31'

DECLARE @TempData TABLE(
    [QuoteID] int,
    [QuoteGUID] [uniqueidentifier] NOT NULL,
    [CompanyLocationGuid] [uniqueidentifier] NULL,
    [UnderwriterUserGuid] [uniqueidentifier] NULL,
    [InsuredGuid] [uniqueidentifier] NULL,
    [ProducerGuid] [uniqueidentifier] NULL,
    [ProducerContactGuid] [uniqueidentifier] NULL,
    [EffectiveDate] datetime NULL,
    --[InvoiceDate] datetime NULL,
    [AccountingDate] datetime NULL,
    [PolicyTypeID] tinyint NOT NULL,  --------------
    [TransactionTypeID] varchar(2)  NULL,  
    [QuoteStatusID] tinyint NOT NULL,
    [PolicyNumber] [varchar](150) NULL,
    [StateID] [char](2) NULL,
    [Premium] [money] NULL,
    BondRate decimal (5,4) NULL,
    [PenalLiability] [money] NULL,
    [CompanyCommission] decimal(3,2) NULL
)

    INSERT INTO @TempData
    SELECT      
                INV.QuoteID,
                tblQuotes.QuoteGUID,
                tblQuotes.CompanyLocationGuid,
                tblQuotes.UnderwriterUserGuid,
                tblSubmissionGroup.InsuredGuid,
                tblProducerLocations.ProducerGUID,
                tblQuotes.ProducerContactGuid,
                INV.EffectiveDate,
                INV.InvoiceDate,
                tblQuotes.PolicyTypeID,
                tblQuotes.TransactionTypeID, 
                tblQuotes.QuoteStatusID,
                tblQuotes.PolicyNumber,         
                tblQuotes.StateID, 
                SUM(ISNULL(tblDetailed.AmtBilled, 0)) AS Premium,
                 [Dynamic_Data_SuretyPRC].BondRate,
                 [Dynamic_Data_SuretyPRC].BondAmount,
                 [Dynamic_Data_SuretyPRC].CompanyComm
    FROM            tblFin_Invoices INV
    INNER JOIN      tblQuotes ON INV.QuoteID = tblQuotes.QuoteID
    INNER JOIN      tblProducerLocations ON INV.ProducerLocationGUID = tblProducerLocations.ProducerLocationGUID  
    INNER JOIN      tblSubmissionGroup ON tblQuotes.SubmissionGroupGuid = tblSubmissionGroup.SubmissionGroupGUID 
    LEFT  JOIN      [dbo].[Dynamic_Data_SuretyPRC] ON Dynamic_Data_SuretyPRC.QuoteGUID = tblQuotes.QuoteGUID
    LEFT  JOIN      tblFin_InvoiceDetail tblDetail ON tblDetail.InvoiceNum = INV.InvoiceNum AND tblDetail.ChargeType = 'P'
    WHERE 
            INV.Failed = 0
            AND CAST(dbo.tblQuotes.EffectiveDate as date) BETWEEN @EffDateFrom AND @EffDateTo 
            AND dbo.tblQuotes.LineGUID = '6E00868B-FFC3-4CA0-876F-CC258F1ED22D'
    GROUP BY INV.QuoteID,
                tblQuotes.QuoteGUID,
                tblQuotes.CompanyLocationGuid,
                tblQuotes.UnderwriterUserGuid,
                tblSubmissionGroup.InsuredGuid,
                tblProducerLocations.ProducerGUID,
                tblQuotes.ProducerContactGuid,
                INV.EffectiveDate,
                INV.InvoiceDate,
                tblQuotes.PolicyTypeID,
                tblQuotes.TransactionTypeID, 
                tblQuotes.QuoteStatusID,
                tblQuotes.PolicyNumber,         
                tblQuotes.StateID, 
                 [Dynamic_Data_SuretyPRC].BondRate,
                 [Dynamic_Data_SuretyPRC].BondAmount,
                 [Dynamic_Data_SuretyPRC].CompanyComm
    ORDER BY    INV.InvoiceDate

【讨论】:

  • 谢谢埃里克。很有帮助!
猜你喜欢
  • 2018-08-20
  • 2018-06-14
  • 2014-10-10
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
相关资源
最近更新 更多