使用具有标量函数的条件和使用交叉应用的条件表值函数

时间:2016-05-06 00:16:03

标签: sql sql-server optimization user-defined-functions

我正在尝试为我正在创建的存储过程确定最佳方法(最快!)。这是一个相当基本的存储过程,用于比较两个系统之间的字段以确保数据完整性。起初我虽然使用临时表和添加索引,但我没有看到速度上的任何差异。然后,在通过表值函数读取性能增益时,我认为这是一种方法,但是一些简单的测试没有显示出任何改进。我甚至担心优化我的查询的原因是因为where条件将使用许多标量函数,因为系统之间的字段长度不匹配(整个其他问题),所以我假设在where子句中做很多标量函数对于性能

以下是方法#1:

SELECT
SLXID
FROM dbo.Salesforce_Contacts a WITH(NOLOCK)
JOIN _SLX_Contact b WITH(NOLOCK)
    ON a.SLXID = b.Contactid
WHERE
a.IsDeleted = 0
AND
(
LEFT(a.FirstName, 32) != b.FirstName
AND LEFT(a.LastName, 32) != b.LastName
AND LEFT(a.Title, 64) != b.Title
AND dbo.GetSLXContactStatus(a.Contact_Status__c) != b.Status
)

这是使用表值函数的方法#2:

SELECT
a.SLXID
FROM dbo.Salesforce_Contacts a WITH(NOLOCK)
JOIN _SLX_Contact b WITH(NOLOCK)
ON a.SLXID = b.Contactid
CROSS APPLY
dbo._SFContact_Functions_TEMP(a.FirstName, a.LastName, a.Title, a.Contact_Status__c)  CA
WHERE 
a.IsDeleted = 0
AND
(
b.FirstName != CA.FirstName_32
AND b.LastName != CA.LastName_32 -- etc.
AND b.Title != CA.Title_64
AND b.Status != CA.Contact_Status
)

以下是#2中使用的表值函数:

ALTER FUNCTION dbo._SFContact_Functions_TEMP 
( 
 @FirstName VARCHAR(40) 
,@LastName VARCHAR(80)
,@Title VARCHAR(128)
,@Status VARCHAR(20)
)

RETURNS TABLE

AS

RETURN

SELECT 
 LEFT(@FirstName, 32) FirstName_32
,LEFT(@LastName, 32) LastName_32
,LEFT(@Title, 64) Title_64
,dbo.GetSLXContactStatus(@Status) Contact_Status
GO

最后这里是执行计划(实际):

#1 #1 对于#2 #2 非常感谢任何帮助或建议!

2 个答案:

答案 0 :(得分:0)

第一种方法更好。

首先,您要做的是什么?数据库设计似乎是错误的。

这是一次性查询或永久性查询。

假设你要做的事情是正确的,那么20-40秒的时间要少得多。

同时显示dbo.GetSLXContactStatus(a.Contact_Status__c)中的内容。

可能会像这样尝试一次,

tABLE dbo.Salesforce_Contacts
cLUSTERED INDEX ON SLXID
Create non clusterindex on IsDeleted AND INCLUDE COLUMN(FirstName,LastName,Title)

tABLE dbo._SLX_Contact
cLUSTERED INDEX ON Contactid

;With CTE
(
 SELECT SLXID ,LEFT(a.FirstName, 32) FirstName, LEFT(a.LastName, 32) LastName
, LEFT(a.Title, 64) Title
FROM dbo.Salesforce_Contacts a WITH(NOLOCK)

WHERE
a.IsDeleted = 0

)

select * from CTE
JOIN _SLX_Contact b WITH(NOLOCK)
    ON a.SLXID = b.Contactid
WHERE 
a.FirstName=! b.FirstName
 AND (a.LastName != b.LastName
AND a.Title != b.Title
AND dbo.GetSLXContactStatus(a.Contact_Status__c) != b.Status-- EXPLAIN THIS
)

如果您有很多记录,那么您可以将CTE记录插入到具有正确索引的TEMP表中

答案 1 :(得分:0)

从提供的图片来看,性能几乎没有差异,自动优化的计划#1和#2。 SSMS提示您额外的索引。分析#1和#2,如果它们不同(几乎不可能)。尝试添加提供的索引。分析计划的确切用途。