sql >> Base de Datos >  >> RDS >> Database

Recortar el tiempo de fecha y hora:un seguimiento

Continuando con mi publicación anterior sobre recortar el tiempo de la fecha y la hora, me animó a demostrar más claramente las características de rendimiento de varios métodos sin involucrar el acceso a los datos. En la publicación original, comparé rápidamente siete métodos diferentes para convertir un valor de fecha y hora en una fecha de forma independiente, mostré que las diferencias eran insignificantes y luego pasé directamente a analizar el uso de esos métodos en consultas reales que devuelven datos.

En esta publicación, quería mostrar varias formas diferentes de recortar el tiempo de la fecha y hora (¡de hecho, 18 formas diferentes!), Sin introducir ningún dato real, para ver si podíamos proclamar una forma "más rápida" de realizar esta tarea.

Los Métodos

Estos son los 18 métodos que estaría probando, algunos tomados de la publicación de blog que Madhivanan señaló después de mi publicación anterior:

DECLARE @d DATETIME, @ds DATETIME = SYSDATETIME();

La prueba

Creé un ciclo donde ejecutaría cada conversión 1,000,000 de veces y luego repetiría el proceso para los 18 métodos de conversión 10 veces. Esto proporcionaría métricas para 10 000 000 de conversiones para cada método, eliminando cualquier sesgo estadístico significativo.

CREATE TABLE #s(j INT, ms INT);
GO
SET NOCOUNT ON;
GO
DECLARE @j INT = 1, @x INT, @i INT = 1000000;
DECLARE @t DATETIME2, @d DATETIME, @ds DATETIME = SYSDATETIME();
 
WHILE @j <= 18
BEGIN
  SELECT @x = 1, @t = SYSDATETIME();
 
  WHILE @x <= @i
  BEGIN
    IF @j = 1
      SET @d = DATEDIFF(DAY, 0, @ds);
    IF @j = 2
      SET @d = CAST(@ds AS INT);
    IF @j = 3
      SET @d = CAST(CONVERT(CHAR(8), @ds, 112) AS DATETIME);
    IF @j = 4
      SET @d = DATEADD(DAY, DATEDIFF(DAY, 0, @ds), 0);
    IF @j = 5
      SET @d = CAST(CAST(SUBSTRING(CAST(@ds AS BINARY(8)), 1, 4) 
               AS BINARY(8)) AS DATETIME);
    IF @j = 6
      SET @d = CONVERT(CHAR(8), @ds, 112);
    IF @J = 7
      SET @d = CAST(CAST(@ds AS VARCHAR(11)) AS DATETIME);
    IF @J = 8
      SET @d = @ds - CONVERT(CHAR(10), @ds, 108);
    IF @J = 9
      SET @d = @ds - CAST(CAST(@ds AS TIME) AS DATETIME);
    IF @J = 10
      SET @d = CAST(FLOOR(CAST(@ds AS FLOAT)) AS DATETIME);
    IF @J = 11
      SET @d = CAST(CAST(CAST(CAST(@ds AS BINARY(8)) AS BINARY(4)) 
               AS BINARY(8)) AS DATETIME);
    IF @J = 12
      SET @d = @ds - CAST(@ds AS BINARY(4));
    IF @J = 13
      SET @d = DATEADD(DAY, CONVERT(INT, @ds - 0.5), 0);
    IF @J = 14
      SET @d = CONVERT(DATETIME, FORMAT(@ds, N'yyyy-MM-dd'));
    IF @J = 15
      SET @d = CONVERT(DATETIME,CONVERT(INT,CONVERT(FLOAT,@ds)));
    IF @J = 16
      SET @d = CAST(CAST(CAST(CAST(@ds AS BINARY(8)) AS BIGINT) & 
               0XFFFFFFFF00000000 AS BINARY(8)) AS DATETIME);
    IF @J = 17
      SET @d = CONVERT(DATE, @ds);
    IF @j = 18
      SET @d = CAST(@ds AS DATE);
 
    SET @x += 1;
  END
 
  INSERT #s SELECT @j, DATEDIFF(MILLISECOND, @t, SYSDATETIME());
 
  SET @j += 1;
END
GO 10
 
SELECT 
  j, method = CASE ... END, 
  MIN(ms), MAX(ms), AVG(ms)
FROM #s
GROUP BY j ORDER BY j;

Los resultados

Ejecuté esto en una VM con Windows 8, con 8 GB de RAM y 4 vCPU, ejecutando SQL Server 2012 (11.0.2376). Estos son los resultados tabulares, ordenados por duración promedio, los más rápidos primero:

Y aquí hay una representación gráfica de la duración promedio: