Convert Implicit and The Related Performance Issues With SQL Server
Convert Implicit and The Related Performance Issues With SQL Server
The tool tip for the index scan gives the details that make all the difference, as
shown below.
The red arrow points to the problem. The function call CONVERT_IMPLICIT(int,
[AdventureWorks].[HumanResources].[Employee].[NationalIDNumber, 0) is
modifying the NationalIDNumber column before it is compared to the integer
constant 1124579811 which we are passing into this query. If you look at the table
definition you'll see that NationalIDNumber is declared to be nvarchar(15). Once
there is a function, even an implicit one as we see here, used on the column SQL
Server can't use the index on NationalDNumber and it falls back on a scan.
Changing the query to compare to a string constant and the problem goes away:
SELECT EmployeeID, NationalIDNumber, LoginID
FROM HumanResources.Employee
WHERE NationalIDNumber = '112457891'
go
The messages now shows that there are zero scans, which is what we want. In this
case the difference in logical reads is only 2, that's because the Employee table is
so small. Working with a million row table, the difference in logical reads grows
into the thousands.
EmployeeID NationalIDNumber LoginID
----------- ---------------- ---------------------4 112457891
adventure-works\rob0
(1 row(s) affected)
Table 'Employee'. Scan count 0, logical reads 4, physical reads 0, read-ahead reads 0,
lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
The query plan shows the seek and the key lookup which is what we would have
expected to occur.
This problem is common where a character string has been used to store a numeric
key. SQL Server will dutifully perform the implicit conversion and return the correct
result, but at the cost of poor performance by doing a scan instead of a seek and
using the index correctly.
Next Steps
I've even seen this problem when varchar columns are compared to
nvarchar columns.
Fixing the problem is straight forward, just make sure you are performing
the comparison on like data types.