Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Index seek with coalesce

I have a table [MyTable] with a column [MyColumn] NVarchar(50). I have a nonclustered index on this column, now while running the below two queries:

SELECT  1
FROM    [MyTable] M
WHERE   M.[MyColumn] = @MyColumn

SELECT  1
FROM    [MyTable] M
WHERE   M.[MyColumn] = COALESCE(@MyColumn, M.[MyColumn] )   

I noticed the first query is using Index Seek (NonClustered) and the second one is using Index Scan (Non Clustered). May I know how will I make use of index seek with coalesce or isnull ?

like image 274
Rocky Singh Avatar asked May 31 '11 11:05

Rocky Singh


People also ask

Which is faster Isnull or coalesce?

For your specific case I would say isnull is clearly faster. This is not to say it is better in any other given situation. Using straight up values, or nvarchars or bits instead of int, or a column that is not a primary key, or Nesting isnull versus adding parameters to coalesce could change things.

Which is faster coalesce or case?

COALESCE() is literally shorthand for a CASE statement, they will perform identically. However, as podiluska mentioned, ISNULL() can be occasionally faster than a CASE statement, but it's likely to be a miniscule increase as these functions are very unlikely to bottleneck your procedure.

Can we use coalesce in Join condition?

A COALESCE function returns the first non-NULL expression from a specified list. Usually, we use COALESCE as one of the elements in the select list, however, it can be successfully used in the join conditions too.

Can you use coalesce in where clause?

You can use coalesce anywhere, including the where clause, yes.


2 Answers

May I know how will I make use of index seek with coalesce or isnull ?

Perhaps not an answer to your question but you can have two different queries. One for the case where @MyColumn is null and one for the case where you want to use @MyColumn in the where clause.

IF @MyColumn IS NULL
BEGIN
  SELECT  1
  FROM    [MyTable] M
END  
ELSE
BEGIN
  SELECT  1
  FROM    [MyTable] M
  WHERE   M.[MyColumn] = @MyColumn
END  
like image 165
Mikael Eriksson Avatar answered Oct 20 '22 04:10

Mikael Eriksson


This isn't easy, since as Alex pointed out using the functions forces a scan, since the optimizer knows it needs to check every row.

What you CAN do is created a Computed Column for the result of your function, and index that column.

There's not really a prettier way to get a seek.

EDIT:

In rereading your question, this may not be an option for you unless you rethink your logic. You are integrating a variable into the function, and there is absolutely no way to index that.

EDIT 2:

Instead of your current logic, try something like:

...
WHERE (M.[MyColumn] = @MyColumn 
       OR @MyColumn IS NULL)
like image 31
JNK Avatar answered Oct 20 '22 03:10

JNK