提高表值功能性能

时间:2016-11-17 08:44:39

标签: sql-server tsql query-performance

你能否帮我改进表值函数:

    Create Function [dbo].[xxx](@InvoiceId numeric(18 ,0) ,@InvoiceType int ,@ReceiptAccOwner int)
    Returns Table
    As
    Return(


    Select * From(

            Select N'InvoiceReceiptNo' + Cast(ROW_NUMBER() over(order by ir.ReceiptRecID) as nvarchar(10)) As row

                ,ir.StockHoldingInvoiceID As InvoiceId

                ,ir.ReceiptNo As ReceiptValue
                ,ir.ReceiptAccOwner
            from InvoiceReceipt As ir       
            Where  ir.ReceiptAccOwner = @ReceiptAccOwner
            And (
                   (ir.StockHoldingInvoiceID = @InvoiceId And @InvoiceType in(1 ,6 ,8) )
                 or(ir.THCInvoiceID = @InvoiceId And @InvoiceType = 2)
                 or(ir.EvaluatInvoiceID = @InvoiceId And @InvoiceType = 3)
                 or(ir.StripInvoiceID = @InvoiceId And @InvoiceType = 4)
                 or(ir.EvaluationExportInvoiceID = @InvoiceId And @InvoiceType = 5)
                 or(ir.ServiceInvoiceID = @InvoiceId And @InvoiceType = 7)
                 or(ir.MovementInvoiceId = @InvoiceId And @InvoiceType = 10)
                 or(ir.InterchangeReplicaInvoice = @InvoiceId And @InvoiceType = 11)
                 or(ir.MovementInvoiceId = @InvoiceId And @InvoiceType = 12)
                 or(ir.BLConsigneeChangeRequestInvoiceID = @InvoiceId And @InvoiceType = 15)
                 )

            UNION All

            Select N'InvoiceReceiptPrice' + Cast(ROW_NUMBER() over(order by ir.ReceiptRecID) as nvarchar(10)) As row

                ,ir.StockHoldingInvoiceID

                ,Cast(IsNull(ir.ReceiptPrice ,0) as nvarchar(20)) As ReceiptValue
                ,ir.ReceiptAccOwner
            from InvoiceReceipt As ir
            Where  ir.ReceiptAccOwner = @ReceiptAccOwner
            And (
                   (ir.StockHoldingInvoiceID = @InvoiceId And @InvoiceType in(1 ,6 ,8) )
                 or(ir.THCInvoiceID = @InvoiceId And @InvoiceType = 2)
                 or(ir.EvaluatInvoiceID = @InvoiceId And @InvoiceType = 3)
                 or(ir.StripInvoiceID = @InvoiceId And @InvoiceType = 4)
                 or(ir.EvaluationExportInvoiceID = @InvoiceId And @InvoiceType = 5)
                 or(ir.ServiceInvoiceID = @InvoiceId And @InvoiceType = 7)
                 or(ir.MovementInvoiceId = @InvoiceId And @InvoiceType = 10)
                 or(ir.InterchangeReplicaInvoice = @InvoiceId And @InvoiceType = 11)
                 or(ir.MovementInvoiceId = @InvoiceId And @InvoiceType = 12)
                 or(ir.BLConsigneeChangeRequestInvoiceID = @InvoiceId And @InvoiceType = 15)
                 )

    ) As tb
    pivot(
             Max(ReceiptValue) --,Sum(ReceiptPrice)
             For row in ([InvoiceReceiptNo1] ,[InvoiceReceiptNo2] ,[InvoiceReceiptNo3] ,[InvoiceReceiptNo4] ,[InvoiceReceiptNo5] ,[InvoiceReceiptNo6] 
                        ,[InvoiceReceiptPrice1] ,[InvoiceReceiptPrice2] ,[InvoiceReceiptPrice3] ,[InvoiceReceiptPrice4] ,[InvoiceReceiptPrice5] ,[InvoiceReceiptPrice6])
         )   piv


    )

我在存储过程中使用此函数,并在select语句中使用Outer 此函数应该只返回每张发票的一条记录。

XML执行计划: 从[dbo]中选择*。[fn_GetInvoiceReceiptInfo](149735,1,1) https://anotepad.com/notes/wh34ey

2 个答案:

答案 0 :(得分:2)

答案取决于您拥有的索引。除非您具体详细说明您拥有的索引和使用的索引,否则很难找到更好的解决方案。

例如,您有一个聚合窗口函数,可以通过更改聚类索引或为特定查询添加覆盖索引来加快速度。然而,只有这确实是瓶颈才有意义。

执行计划说了什么?

您可能想要尝试的另一件事是在OR子句中重写所有不带WHERE的查询,并对所有查询使用UNION ALL。这将允许数据库并行化您的查询。

同样,这些是您可以尝试的,但它们是否有效取决于索引和查询计划瓶颈。

答案 1 :(得分:1)

好的,所以看看你提供的执行计划你正在做Key Lookups,这意味着你可以调整一个索引来减少这里的执行时间。

目前,您正在使用表Relationship_82_FK上的索引InvoiceReceipt来返回两个值ReceiptRecIDStockHoldingInvoiceID。现在,因为此索引不包含您需要的所有信息,SQL必须返回并查看聚簇索引以返回其他信息。尝试更改索引Relationship_82_FK以将ReceiptAccHolderReceiptPrice作为包含字段。