1

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

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 为空或空白,我可以排除标记表上的连接的最“高性能”方式是什么?

4

3 回答 3

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 是一种声明性数据访问语言,而不是您的应用程序命令式处理语言。您声明的任何查询都必须创建适用于所有情况的访问路径。在查询中包含条件逻辑是您能做的最糟糕的事情,它强制访问计划通常扫描所有可能的数据,因为它们无法在计划创建时确定条件是真还是假。

于 2010-10-29T22:54:44.310 回答
0

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

或者您不想因在标签上加入 @searchTags 而导致性能损失?

在您的示例中,@searchtags 中的数据来自哪里并不是很清楚。

LEFT JOIN Tags t on t.TagId = bt.TagId AND @tagstring is not null AND @tagstring <> ''

服务器应该足够聪明,不会在存在这种情况的情况下尝试加入。在任何情况下,我都不认为这会导致任何显着的性能下降。

如果由于某种原因您希望在结果中根本不显示列,则具有两个不同查询的 IF...ELSE 块是实现此目的的最简单方法。

于 2010-10-29T22:36:30.407 回答
0

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

因此,您可以将 SELECT 语句移动到 IF 语句中,当为 true 时。

于 2010-10-29T22:54:16.123 回答