2010-12-01 20 views
2

用戶定義函數用於存儲過程。用戶定義函數返回標量值。用戶定義函數中使用的邏輯如下如何修復SQL Server 2005中的用戶定義函數標量值性能問題?

CREATE FUNCTION [dbo].[udf_Test] (@Code varchar(10), ) 
    RETURNS bit AS  
BEGIN 
    DECLARE @bFlag bit 

    SELECT @bFlag = COUNT(id) 
    FROM tbL1 
    WHERE Code = @Code 

    IF @bFlag = 0 
    BEGIN 
    SELECT @bFlag = COUNT(id) 
     FROM tbl2 
    WHERE LTRIM(RTRIM(Code)) = @Code 
    END 

    IF @bFlag = 0 
    BEGIN 
    SELECT @bFlag = COUNT(id) 
     FROM tbl3 
    WHERE LTRIM(RTRIM(Code)) = @Code 
    END 

    IF @bFlag = 0 
    BEGIN 
    SELECT @bFlag = COUNT(id) 
     FROM tbl4 
    WHERE LTRIM(RTRIM(Code)) = @Code 
    END 

RETURN @bFlag 

這是正確的方法來提高上述用戶定義函數的性能嗎?

+0

既然你只返回一個開/關位,你如果有一個或多個記錄滿足條件的唯一感興趣嗎? – 2010-12-01 17:12:20

+2

這是誤用時的性能問題。喜歡這個。 – gbn 2010-12-01 17:34:38

回答

8

提高性能的最佳方法是完全丟棄UDF。這發生在我

一個眼前的事情是,

LTRIM(RTRIM(Code)) = @Code 

不優化搜索,以便每次調用(即每一行中的外部查詢返回)可能導致多達4次表掃描。

如果在查詢中用內聯CASE表達式替換UDF中的邏輯,您可能會收到much superior execution plan。即使您不能使謂詞sargable至少它可以讓優化器探索不同的連接策略,如散列連接,而不是強制重複掃描相同的表。

2

因爲它的立場...

WHERE LTRIM(RTRIM(Code)) = @Code;使用LTRIM的(RTRIM(..將阻止使用索引。

理想情況下,你應該有ltrim(rtrim(Code))結果作爲索引山坳使索引可以在WHERE子句中使用,這將加快速度。

設置@bFlag = COUNT(id)@bFlag是一個int和COUNT(id)一個int不是很好!你真的應該使用CASE WHEN COUNT(id) > 0 THEN 1 ELSE 0 END或以其他方式。

但是,使用IF EXISTS的方法更爲有效,因爲一旦找到符合您的標準的單個行就會短路。

DECLARE @bFlag bit 
SELECT @bFlag = 0 

IF EXISTS (SELECT 'x' FROM tbl1 where Code= @Code) SELECT @bFlag = 1 
-- etc. 
RETURN @bFlag 
相關問題