Buenas a todos de nuevo, el lunes estaba viendo la tele tranquilamente en el sofá viendo el CSI, cuando al ver quien era el malo, me dije, joder nada es lo que parece. Entonces me acordé no me digáis porque, yo creo que era que estaba ya medio dormido o que, de los campos DateTime en SQL Server y como se comportan cuando son índices en una SELECT, si dicha tabla tiene 10000 registros o 7000000 de registros.
En este post voy a intentar dar una visión de cómo trata los campos DateTime SQL Server, bien, imaginamos que tenemos la siguiente tabla:
Pedidos
PK_Pedido int à Está es la Clave Principal
Fecha DateTime à Este campo es Inidce
Transporte int à Este campo es Indice (1 Camión, 2 Barco, 3 Avión, 4 Tren)
FK_Cliente int
Clientes
PK_Cliente à Está es la Clave Principal
NombreCliente à Descripción
Hasta aquí hemos entendido todos la estructura de las tablas que a partir de ahora van a intervenir. La SELECT con la que vamos a experimentar va a ser la siguiente:
SELECT PK_Pedido, Fecha, Transporte, NombreCliente
FROM Pedidos INNER JOIN Clientes ON FK_Cliente = PK_Cliente
WHERE Fecha Between ‘20070101’ and ‘20070131’ and Transporte = 1
Si está SELECT la hacemos cuando la tabla tiene pocos registros, cuando hablo de pocos no quiero decir 100 sino algo menor a 1000000, si nos fijamos en el analizador de SQL, nos dice que el índice utilizado en dicha SELECT es el campo fecha, debido a que al tener pocos registros las variantes no son demasiadas, pero si está misma SELECT lo hacemos cuando tenemos por ejemplo 7000000 de registros, SQL Server nunca va a utilizar el campo fecha como índice debido a su gran probabilidad de posibles fechas que puede haber, aunque en el rango de 1 mes nosotros sepamos que se puede encontrar sólo con 30 registros, entonces vamos a tener una pérdida de rendimiento considerable, ya que si a todos esos registros primero separamos por Transporte es menos eficiente.
Una posible solución para optimizar este tema sería pasar el campo Fecha de DateTime a SmallDateTime, pero esto solo nos serviría si no nos interesa nunca los segundos de la Fecha, pero si necesitaríamos los segundos y milisegundos, sólo nos quedaría una solución, que sería forzar a la SELECT a que vaya por el campo Fecha y sería de esta forma:
SELECT PK_Pedido, Fecha, Transporte, NombreCliente
FROM Pedidos (Index = IX_Pedidos_Fecha) INNER JOIN Clientes ON FK_Cliente = PK_Cliente
WHERE Fecha Between ‘20070101’ and ‘20070131’ and Transporte = 1
Espero que se haya entendido el ejemplo, y que a alguien le sirva de algo, nos vemos en el siguiente post.