2012-04-10 25 views
5

En Scaling Up Your Data Warehouse with SQL Server 2008 R2, el autor recomienda utilizar una clave de fecha entera en el formato de AAAAMMDD como un índice agrupado en sus tablas de hechos para ayudar a optimizar la velocidad de la consulta.TSQL DateTime to DateKey Int

¿Cuál es la mejor manera de convertir su campo de fecha clave en la tecla de fecha? Siento que el siguiente iba a funcionar, pero es un poco descuidado:

select Replace(CONVERT(varchar,GETDATE(),102),'.','') 

Está claro que no estoy usando getdate, sino más bien una columna de fecha en la tabla que va a utilizar en mis agregaciones.

En primer lugar, ¿cómo sugeriría hacer esta conversión? Es mi idea aceptable?

En segundo lugar, ¿alguien ha tenido mucho éxito al usar la clave de fecha como índice agrupado?

Respuesta

8

ISO larga (112) que hacer el truco:

SELECT CONVERT(INT, CONVERT(VARCHAR(8), GETDATE(), 112)) 

getdate Fundición() directamente a int con la norma ISO 41008 112 da por alguna razón, pero ir a través de un VARCHAR parece funcionar - Voy a actualizar si pienso en un elenco más rápido.

EDITAR: En lo que respecta a la int sólo se debate frente varchar, aquí están mis conclusiones (repetible en mi banco de pruebas & servidor de producción) Método Varchar utiliza menos tiempo de CPU de medio millón de moldes, pero una fracción más lento en general - insignificante a menos que su trato con mil millones de filas

EDIT 2: revisado de casos de prueba a borrar la memoria caché y las fechas diferentes personas

DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT YEAR([Date]) * 10000 + MONTH([Date]) * 100 + DAY([Date]) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 218 ms, elapsed time = 255ms.  
DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT CONVERT(INT, CONVERT(VARCHAR(8), [Date], 112)) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 266 ms, elapsed time = 602ms 
+1

convertir getdate() directamente a INT con IS 112 41008 da debido a que es el número de días desde la fecha 0. Puede validar comparando ese resultado con el resultado de DATEDIFF entre 0 y GETDATE(). 'SELECT CONVERTIR (INT, GETDATE(), 112), DATEDIFF (día, 0, GETDATE())' –

+0

@AdamPorad +1 Saludos por aclarar que – HeavenCore

+1

Creo que su prueba es defectuosa. La diferencia en el tiempo transcurrido es el resultado de mostrar la larga lista de valores en la pantalla.Además, está utilizando GetDate() para que SQL Server lo reconozca como una constante y no realice el cálculo para cada fila. Necesita usar una columna de la tabla actual. Por último, para evaluar con precisión el rendimiento, debe eliminar los búferes limpios y liberar el caché de procedimientos. No deberías hacer esto en un servidor de producción. –

2

la conversión a cadenas y viceversa puede ser sorprendentemente lenta . En su lugar, se podría tratar en su totalidad con números enteros, como esto:

Select Year(GetDate()) * 10000 + Month(GetDate()) * 100 + Day(GetDate()) 

En mi breve ensayo, esto es ligeramente más rápido que la conversión a cadena y luego a int. Las funciones Año, Mes y Día devuelven un número entero, por lo que el rendimiento es ligeramente mejor.

4

En lugar de crear una DateKey con el formato AAAAMMDD, puede usar la función DATEDIFF para obtener el número de días entre 0 (es decir, "la fecha representada por 0") y la fecha para la que está haciendo DateKey.

SELECT DATEDIFF(day,0,GETDATE()) 

El inconveniente es que no se puede buscar fácilmente en el valor y determinar la fecha, pero se puede utilizar la función DATEADD para calcular la fecha original (También he visto este truco utilizado truncar la parte de hora de una fecha y hora).

SELECT DATEADD(day, 41007, 0) 

(Nota: 41007 es el resultado de la función DATEDIFF encima cuando me encontré en 4/10/2012.)