【问题标题】:Does using format() allow sql server to use that column for selecting the right index?使用 format() 是否允许 sql server 使用该列来选择正确的索引?
【发布时间】:2022-01-07 15:38:58
【问题描述】:

今天我在查看一个执行计划时看到一条消息,上面说转换线可能会影响基数估计。我做了一些进一步的研究,发现函数的使用会影响 SQL Server 估计基数的能力,因为该列实际上变得不可见。见here。查询中有一个列正在从小日期时间转换为 varchar,然后被转换回日期。看起来原始开发人员试图提供两次相同的列,一次作为完整日期时间,一次作为短日期。 CAST(CONVERT(VARCHAR(12), ELI.DDC1Date, 101) AS DATETIME) AS ShortDDC1Date 无论如何,我将select中的列更新为FORMAT(eli.ddc1date, 'YYYY-MM-DD') as ShortDDC1Date,并再次查看了执行计划。关于转换影响基数估计的警告已经消失。格式化函数对 SQL Sever 使用索引的能力有影响吗?如果是这样,为什么?

SELECT ELI.EInvoiceLineItemID
    ,ELI.EInvoiceID
    ,ELI.VendorID
    ,ELI.ServicerID
    ,ELI.CategoryID
    ,ELI.SubcategoryID
    ,ELI.ItemDate
    ,ELI.ItemQuantity
    ,ELI.ItemPrice
    ,ELI.AmountBilledToDate
    ,ELI.LifeofLoanTotalAllowable
    ,ELI.InvoiceTotalAllowable
    ,ELI.UnitAllowable
    ,ELI.GuidelineTypeID
    ,ELI.DDC1Date
    ,ELIP.CheckRequestID
    ,ELIP.PaymentTransactionID
    ,ELIP.NIPaymentTransactionID
    ,ELIP.NIPaymentDate
    ,ELIP.ACH
    ,ELIP.PaidDate
    ,ELIP.PaymentError
    ,ELIP.PaymentErrorDetail
    ,ELI.Adjusted
    ,ELI.Utility
    ,ELI.AdjustedAmount
    ,ELI.ExportedFilename
    ,ELIP.DisbursementAmount
    ,ELIP.CorporateAdvanceAmount
    ,ELIP.TransCode
    ,ELIP.CawPayeeCode
    ,ELIP.ReasonCode
    ,ELIP.SeqCode
    ,ELI.BatchCode
    ,ELIP.ProcCode
    ,ELI.UserComment
    ,ELI.BreakdownFromDate
    ,ELI.BreakdownToDate
    ,ELI.BreakdownBaseAmount
    ,ELI.BreakdownInterestAmount
    ,ELI.BreakdownPenaltyAmount
    ,ELI.BreakdownAdvanceDate
    ,ELI.ImageAttachment
    ,ELI.LineItemBreakdown
    ,ELI.CommentRequired
    ,ELI.ImageRequired
    ,ELI.ExceptionFlag
    ,ELI.DateCreated
    ,ELI.DateUpdated
    ,ELI.RequiredImagesAttached
    ,ELI.AmountBilledToDateOnOrder
    ,ELI.OrderTotalAllowable
    ,ELIP.PhaseCode
    ,ELI.DataServicerOrderID
    ,ELI.ServiceFromDate
    ,ELI.ServiceToDate
    ,ELI.CawPayeeCodeManualOverride
    ,ELI.OTAAmount
    ,ELI.PreviouslyBilledDate
    ,ELI.PreviouslyPaidDate
    ,CAST(CONVERT(VARCHAR(12), ELI.DDC1Date, 101) AS DATETIME) AS ShortDDC1Date
    ,S.ServicerCode
    ,M.RegionCode
    ,ELIP.SplitTypeID
FROM [dbo].EInvoiceLineItem ELI WITH (NOLOCK)
LEFT JOIN dbo.EInvoiceLineItemPayment ELIP WITH (NOLOCK) ON ELI.EInvoiceLineItemID = ELIP.EInvoiceLineItemID
INNER JOIN EInvoice E WITH (NOLOCK) ON ELI.EInvoiceID = E.EInvoiceID
INNER JOIN MasterLoanData M WITH (NOLOCK) ON E.MasterLoanDataID = M.MasterLoanDataID
INNER JOIN [dbo].Servicer S WITH (NOLOCK) ON ELI.ServicerID = S.ServicerID
WHERE ELIP.CheckRequestID > 0

【问题讨论】:

  • 请显示您的整个查询
  • 添加了查询

标签: sql sql-server


【解决方案1】:

如果format() 确实有这种效果,我会非常非常惊讶。问题是第二个参数可以是一个表达式——您甚至不必在每一行上使用相同的格式。

即使没有这种考虑,format() 也可以更改列的顺序,因此索引不能用于order by

我还应该补充一下Aaron Bertrand is waryformat()的表现。

【讨论】:

  • 支持关于 FORMAT 函数性能问题的评论。
  • 我也投了赞成票,因为这是有用的信息,但我没有回答这个问题,因为它不能直接回答问题,也不能解决在以一种可以避免基数估计问题的方式使用不同的格式(这可能是不可能的)。
猜你喜欢
  • 1970-01-01
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多