在IF,OR上表现不佳

时间:2015-05-22 00:15:21

标签: sql sql-server sql-server-2008 tsql

我有类似这样的存储过程:

SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId
WHERE  a.Id = @authorId OR @author = 0

因此,当输入参数@author为> 0它返回特定作者的记录,如果为0则返回每个作者的记录。

即使我为@author传递任何大于0的值,性能也低于标准(尽管它并不是非常慢)。然后我注意到如果我删除OR子句,存储过程运行得更快(对于相同的输入参数,至少快80%)。然后我尝试做类似的事情:

IF @author > 0 
  --select records on a specific author
ELSE
  --select everything

但是,性能与OR非常相似。无论如何以不同的方式编写类似的东西以获得更好的性能?

4 个答案:

答案 0 :(得分:2)

正如Nate S所说,你需要一个索引

但根据我的经验,我使用IN而不是OR

获得了更好的效果
SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId
WHERE  a.Id IN (@authorId, 0)

但总是尝试在execution plan中查看您的查询并比较结果

<强>更新

如果你想要条件WHERE子句,你可以试试这些替代方案。

使用CASE声明

SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId
WHERE  a.Id  = CASE @authorId WHEN 0 THEN a.Id ELSE @authorId END

此外,如果您设置@authorId = NULL而不是0,则可以使用ISNULL函数,但最好不要使用WHERE子句中的函数

SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId
WHERE  a.Id  ISNULL(@authorId, a.Id)

答案 1 :(得分:1)

您应该向表中添加索引,包括where子句中的任何列。这应该在authors表ID列上添加一个索引。

CREATE INDEX 'INDEX NAME'
    ON dbo.Author (ID); 

CREATE INDEX (Transact-SQL)

答案 2 :(得分:0)

使用以下查询,我相信你会得到你的表现

SELECT a.Name AS Author,
           b.Price,
           b.PublishDate,
           b.Title,
           b.ISBN
    FROM   Book b
           INNER JOIN Author a ON b.Id = a.BookId
    WHERE  a.Id IN (@authorId, 0)
    option(OPTIMIZE for(@authorId =10))

答案 3 :(得分:0)

试试这个 Joins讨厌OR

SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId and a.Id = @authorId 
union
SELECT a.Name AS Author,
       b.Price,
       b.PublishDate,
       b.Title,
       b.ISBN
FROM   Book b
       INNER JOIN Author a ON b.Id = a.BookId and @author = 0