提高 Table 值函数性能
Improve Table Value Function Performance
你能帮我改进一下table值函数吗:
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 语句中使用外部应用,
此功能应该 return 每张发票只有一条记录。
XML 执行计划:
Select * 来自 [dbo].[fn_GetInvoiceReceiptInfo](149735 , 1 ,1)
https://anotepad.com/notes/wh34ey
答案取决于您拥有的索引。除非您特别详细说明您拥有哪些索引以及使用了哪些索引,否则很难想出更好的解决方案。
例如,您有一个聚合 window 函数,可以通过更改聚类索引或为您的特定查询添加覆盖索引来使其更快。但是,只有在这确实是瓶颈时才有意义。
执行计划是怎么说的?
您可能想尝试的另一件事是在 WHERE
子句中重写所有不带 OR
的查询,并对所有查询使用 UNION ALL
。这将允许数据库并行化您的查询。
同样,您可以尝试这些方法,但它们是否有效取决于索引和查询计划瓶颈。
好的,查看您提供的执行计划,您正在执行 Key Lookups
这意味着您可以调整索引以减少此处的执行时间。
目前,您在 table InvoiceReceipt
到 return 上使用索引 Relationship_82_FK
这两个值 ReceiptRecID
和 StockHoldingInvoiceID
.现在,由于此索引不包含您需要的所有信息 SQL 必须返回并对照您的聚簇索引查找 return 附加信息。尝试更改索引 Relationship_82_FK
以将 ReceiptAccHolder
和 ReceiptPrice
作为包含字段。
你能帮我改进一下table值函数吗:
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 语句中使用外部应用, 此功能应该 return 每张发票只有一条记录。
XML 执行计划: Select * 来自 [dbo].[fn_GetInvoiceReceiptInfo](149735 , 1 ,1) https://anotepad.com/notes/wh34ey
答案取决于您拥有的索引。除非您特别详细说明您拥有哪些索引以及使用了哪些索引,否则很难想出更好的解决方案。
例如,您有一个聚合 window 函数,可以通过更改聚类索引或为您的特定查询添加覆盖索引来使其更快。但是,只有在这确实是瓶颈时才有意义。
执行计划是怎么说的?
您可能想尝试的另一件事是在 WHERE
子句中重写所有不带 OR
的查询,并对所有查询使用 UNION ALL
。这将允许数据库并行化您的查询。
同样,您可以尝试这些方法,但它们是否有效取决于索引和查询计划瓶颈。
好的,查看您提供的执行计划,您正在执行 Key Lookups
这意味着您可以调整索引以减少此处的执行时间。
目前,您在 table InvoiceReceipt
到 return 上使用索引 Relationship_82_FK
这两个值 ReceiptRecID
和 StockHoldingInvoiceID
.现在,由于此索引不包含您需要的所有信息 SQL 必须返回并对照您的聚簇索引查找 return 附加信息。尝试更改索引 Relationship_82_FK
以将 ReceiptAccHolder
和 ReceiptPrice
作为包含字段。