Conversão Implícita

Posted on maio 21, 2012

5


 

Problema

Analisando algumas consultas no banco de dados com o nosso famoso recurso o Data Collector, vi que havia uma consulta na qual estava custando muito tempo de duração para a execução. Havia um índice criado para suportar a consulta, porém o QO (Query Optmizer) não estava utilizando de forma correta o mesmo para realizar a consulta. Aqui irei mostrar o mesmo problema , só que na base de dados AdventureWorks.

Solução

A consulta realizada foi….

USE AdventureWorks

GO

 SELECT DENSE_RANK() OVER (PARTITION BY Title ORDER BY LoginID) AS RankID,

          EmployeeID, NationalIDNumber, LoginID, Title, BirthDate, MaritalStatus, Gender

FROM HumanResources.Employee

WHERE NationalIDNumber = 671089628

Consultando o NATIONALIDNUMBER, o mesmo possui o índice – AK_Employee_NationalIDNumber

image(Figura 1 – Informações dos Índices da tabela HumanResources.Employee)

 

Porém analisando o plano de execução vemos que:

 

image

(Figura 2 – Plano de Execução da Consulta acima.)

 

O índice foi utilizando como previamos, porém foi realizado um Index Scan ou seja, neste plano de execução foi preciso varer toda a tabela para que o número fosse encontrado. Porque?

 

image

(Figura 3 – Predicado do Plano de Execução da Consulta acima.)

 

CONVERT_IMPLICIT(int,[AdventureWorks].[HumanResources].[Employee].[NationalIDNumber],0)=(671089628)

 

image

(Figura 4 – Informações da tabela HumanResources.Employee.)

 

O problema estava ocorrendo porque o campo no qual estávamos pesquisando é um campo tipo NVARCHAR e estava passando como um tipo int – WHERE NationalIDNumber = 671089628

sendo assim o QO estava tentando realizar a conversão porém não estava conseguindo, e ai estava realizando um SCAN em toda a tabela, tanto é que se compararmos as duas consultas, vemos que:

 

SELECT DENSE_RANK() OVER (PARTITION BY Title ORDER BY LoginID) AS RankID,

          EmployeeID, NationalIDNumber, LoginID, Title, BirthDate, MaritalStatus, Gender

FROM HumanResources.Employee

WHERE NationalIDNumber = 671089628

 

GO

 

SELECT DENSE_RANK() OVER (PARTITION BY Title ORDER BY LoginID) AS RankID,

          EmployeeID, NationalIDNumber, LoginID, Title, BirthDate, MaritalStatus, Gender

FROM HumanResources.Employee

WHERE NationalIDNumber = N’671089628′

 

image

(Figura 5 – Comparação das Consultas acima 74% x 26%.)

 

Porém quando for realizar uma consulta, tome muito cuidado com as conversões implícita dentro do seu código.