Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does wrapping nullable columns in ISNULL cause table scans?

Code analysis rule SR0007 for Visual Studio 2010 database projects states that:

You should explicitly indicate how to handle NULL values in comparison expressions by wrapping each column that can contain a NULL value in an ISNULL function.

However code analysis rule SR0006 is violated when:

As part of a comparison, an expression contains a column reference ... Your code could cause a table scan if it compares an expression that contains a column reference.

Does this also apply to ISNULL, or does ISNULL never result in a table scan?

like image 317
Tom Hunter Avatar asked Sep 19 '11 13:09

Tom Hunter


People also ask

Why should we avoid NULL values in SQL?

They should be avoided to avoid the complexity in select & update queries and also because columns which have constraints like primary or foreign key constraints cannot contain a NULL value.

What is the difference between Isnull and Ifnull?

IFNULL is equivalent to ISNULL. IFNULL is equivalent to COALESCE except that IFNULL is called with only two arguments. ISNULL(a,b) is different from x IS NULL . The arguments can have any data type supported by Vertica.

Are NULLs counted in count SQL?

COUNT(expression) returns the number of values in expression, which is a table column name or an expression that evaluates to a column of data. COUNT(expression) does not count NULL values. This query returns the number of non-NULL values in the Name column of Sample. Person.

What will happen if you are trying to fetch a record which is NULL?

The equal (=) operator is used to compare two expressions values and if the compared values are equal the comparison result will be true. On the other hand, when we try to use an equal operator to find the rows that contain the null values, the result set will return nothing.


1 Answers

Yes it causes table scans. (though seems to get optimised out if the column isn't actually nullable)

The SR0007 rule is extremely poor blanket advice as it renders the predicate unsargable and means any indexes on the column will be useless. Even if there is no index on the column it might still make cardinality estimates inaccurate affecting other parts of the plan.

The categorization of it in the Microsoft.Performance category is quite amusing as it seems to have been written by someone with no understanding of query performance.

It claims the rationale is

If your code compares two NULL values or a NULL value with any other value, your code will return an unknown result.

Whilst the expression itself does evaluate to unknown your code returns a completely deterministic result once you understand that any =, <>, >, < etc comparison with NULL evaluate as Unknown and that the WHERE clause only returns rows where the expression evaluates to true.

It is possible that they mean if ANSI_NULLS is off but the example they give in the documentation of WHERE ISNULL([c2],0) > 2; vs WHERE [c2] > 2; would not be affected by this setting anyway. This setting

affects a comparison only if one of the operands of the comparison is either a variable that is NULL or a literal NULL.

Execution plans showing scans vs seek or below

CREATE TABLE #foo
  (
     x INT NULL UNIQUE
  )

INSERT INTO #foo
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM   sys.all_columns

SELECT *
FROM   #foo
WHERE  ISNULL(x, 10) = 10

SELECT *
FROM   #foo
WHERE  x = 10

SELECT *
FROM   #foo
WHERE  x = 10
        OR x IS NULL 

enter image description here

like image 121
Martin Smith Avatar answered Oct 17 '22 09:10

Martin Smith