enero 12, 2006

Tips para optimización de queries en SQL Server (2)

Otro tip para optimización de una consulta en SQL Server es evitar el uso de funciones explícitas o implícitas en el predicado de la cláusula WHERE. Las columnas en la cláusula WHERE son vistas como expresiones en lugar de columnas. De hecho, las columnas no son utilizadas en el plan de ejecución del optimizador. Un problema común es que las columnas cuyo tipo de dato es datetime. Si tienes una columna de dicho tipo en una cláusula WHERE, y necesitas convertirla o usar como una función de datos, trata de forzar a interpretarla como una expresión de caracteres.

El siguiente query, con una función en la columna datetime causa un barrido de tabla en la base de datos Northwind, inclusive con un índice en la columna OrderDate:

select OrderID from Northwind.dbo.Orders WHERE DATEADD(day, 15, OrderDate) = '07/23/1996'

Sin embargo, si “arreglamos” un poco el query, moviendo la función al otro lado del WHERE, el índice podrá ser utilizado en la columna datetime. De la siguiente manera:

select OrderID from Northwind.dbo.Orders WHERE OrderDate = dateadd(day, -15, '07/23/1996')

A continuación el plan de ejecución gráfico de ambas consultas. En el primer caso, el ícono corresponde a un barrido del índice (Index Scan), mientras que en el segundo corresponde a una búsqueda (Index Seek).



Una vez más, los números hablan por sí solos.

Las conversiones implícitas también pueden ser causa de “barridos”, dado a discordancia en los tipos de datos. Mucho ojo con los tipos de dato varchar y nvarchar, así como con los nchar y nvarchar, dado que pueden ejecutar una conversión implícita. Por ejemplo (la columna CustomerId es del tipo nchar):

declare @CustId char(5)
set @CustId = 'FOLKO'
select CompanyName from Northwind.dbo.Customers where CustomerId = @CustId

Arroja el siguiente plan de ejecución:



No es mucha la diferencia en performance, pero siempre es buena práctica manejar cuidadosamente los mismos tipos de dato.