简体   繁体   中英

Poor Performance on IF, OR

I have a stored procedure similar to something like this:

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

So when the input parameter @author is > 0 it returns records on a specific author, if 0 it returns records on every author.

Even when I pass any values greater than 0 for @author, the performance is sub-par (though it's not terribly slow). I then notice if I remove the OR clause the stored procedure runs much faster (at least 80% faster for the same input parameter). I then try to do something like:

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

However, the performance is pretty the same as OR. Is there anyway to code something like this in a different way to gain better performance?

As Nate S said, you need an index

But in my experience, I got better performance using IN rather than 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)

But always try to see your query in execution plan and compare the result

Update

If you want conditional WHERE clause, you can use try these alternatives.

Using CASE statement

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

Also if you set the @authorId = NULL rather than 0, you can use ISNULL function but better not to use functions in WHERE clause

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)

You should add an index to the table, including any columns in the where clause. This should add an index on the authors table ID column.

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

CREATE INDEX (Transact-SQL)

Use below query and i am sure you will get your performance

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))

Try this
Joins hate 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM