Database
 sql >> Database >  >> RDS >> Database

Ritaglio del tempo da datetime:un follow-up

Facendo seguito al mio precedente post sul taglio del tempo da datetime, sono stato spronato a dimostrare più chiaramente le caratteristiche prestazionali di vari metodi senza coinvolgere l'accesso ai dati. Nel post originale, ho confrontato rapidamente sette diversi metodi per convertire un valore datetime in una data in modo indipendente, ho mostrato che le differenze erano trascurabili, quindi sono passato direttamente all'analisi dell'uso di quei metodi nelle query effettive che restituiscono dati.

In questo post volevo mostrare diversi modi per ritagliare il tempo da datetime (18 modi diversi in effetti!), senza introdurre alcun dato effettivo, per vedere se potevamo proclamare un modo "più veloce" per eseguire questo compito.

I metodi

Ecco i 18 metodi che testerei, alcuni presi dal post del blog che Madhivanan ha indicato dopo il mio post precedente:

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

Il test

Ho creato un ciclo in cui eseguirei ciascuna conversione 1.000.000 di volte, quindi ripetere il processo per tutti i 18 metodi di conversione 10 volte. Ciò fornirebbe metriche per 10.000.000 di conversioni per ciascun metodo, eliminando qualsiasi distorsione statistica significativa.

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;

I risultati

L'ho eseguito su una macchina virtuale Windows 8, con 8 GB di RAM e 4 vCPU, con SQL Server 2012 (11.0.2376). Ecco i risultati tabulari, ordinati per durata media, prima il più veloce:

Ed ecco una rappresentazione grafica della durata media: