SQL - 有条件地排除连接的最佳性能方式? (如果可能的话)

时间:2010-10-29 22:30:34

标签: sql sql-server tsql join database-programming

如果我有以下表结构...

Table 1: BlogPost

PostId |  Name | Text    

Table 2: Tags

TagId  | Tag    

Table 3: BlogPostTag

PostId | TagId

以下存储过程...

CREATE PROCEDURE SearchBlogPosts

    @tagstring nvarchar(max),

AS
BEGIN

    DECLARE @searchTags TABLE (Tag varchar(50));

    IF @tagstring IS NOT NULL AND @tagstring <> ''
        BEGIN
            INSERT INTO @tags SELECT s AS tag FROM dbo.Split(',',@tagstring);
        END

    SELECT * FROM BlogPost b
        JOIN BlogPostTags bt on bt.PostId = b.PostId    
        JOIN Tags t on t.TagId = bt.TagId
        JOIN @searchTags st ON st.Tag = t.Tag
            ...
        (Other Joins and where clauses may exist below here)
END

...如果@tagstring为null或空白,我可以排除标记表上的连接的最“高效”方式是什么?

3 个答案:

答案 0 :(得分:2)

指定条件连接的唯一方法(也是最好的方法)是使用不同的查询:

IF @tagstring IS NOT NULL AND @tagstring <> '' 
BEGIN
    SELECT * FROM BlogPost b 
        JOIN BlogPostTags bt on bt.PostId = b.PostId     
        JOIN Tags t on t.TagId = bt.TagId 
        JOIN @searchTags st ON st.Tag = t.Tag 
END
ELSE
BEGIN
    SELECT * FROM BlogPost b 
        JOIN BlogPostTags bt on bt.PostId = b.PostId     
        JOIN Tags t on t.TagId = bt.TagId 
END

SQL是一种声明性的数据访问语言,而不是您的应用程序命令式处理语言。您声明的任何查询都必须创建一个在所有情况下 的访问路径。在查询中使用条件逻辑是您可以做的最糟糕的事情,它会强制通常扫描所有可能数据的访问计划,因为他们无法确定计划创建时条件是真还是假时间。

答案 1 :(得分:0)

我不认为指定左连接会导致性能下降(如果@tagstring为null或空白,我假设@searchTags为空)。

或者你不想因在标签上加入@searchTags而导致性能下降吗?

在你的例子中,@ searchtags中的数据来自于

,这一点并不十分清楚
LEFT JOIN Tags t on t.TagId = bt.TagId AND @tagstring is not null AND @tagstring <> ''

服务器应该足够智能,以便在存在该条件时根本不尝试加入。在任何情况下,我都不认为这会导致任何显着的性能下降。

如果你因为某种原因想要在结果中没有显示列,那么带有两个不同查询的IF ... ELSE块是最简单的方法。

答案 2 :(得分:0)

我认为如果@tagstring为null或空白,您可以获得的最佳性能是不运行查询。由于所有内部联接和@searchTags都没有行,因此永远不会返回行。

因此,当真正阻塞时,您可以将SELECT语句移动到IF语句中。