sql >> Database >  >> RDS >> Database

Tijd bijsnijden vanaf datetime - een vervolg

In vervolg op mijn vorige bericht over het inkorten van de tijd van datetime, werd ik aangespoord om de prestatiekenmerken van verschillende methoden duidelijker aan te tonen zonder dat er toegang tot gegevens nodig was. In het oorspronkelijke bericht vergeleek ik snel zeven verschillende methoden om een ​​datetime-waarde onafhankelijk van elkaar naar een datum te converteren, toonde aan dat de verschillen te verwaarlozen waren en ging toen direct over tot het analyseren van het gebruik van die methoden in daadwerkelijke zoekopdrachten die gegevens retourneren.

In dit bericht wilde ik verschillende manieren laten zien om de tijd vanaf datetime in te korten (in feite 18 verschillende manieren!), zonder enige feitelijke gegevens te introduceren, om te zien of we een "snelste" manier konden verkondigen om deze taak uit te voeren.

De methoden

Hier zijn de 18 methoden die ik zou testen, sommige ontleend aan de blogpost die Madhivanan aangaf na mijn vorige post:

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

De Test

Ik heb een lus gemaakt waarin ik elke conversie 1.000.000 keer zou uitvoeren en het proces vervolgens 10 keer zou herhalen voor alle 18 conversiemethoden. Dit zou statistieken opleveren voor 10.000.000 conversies voor elke methode, waardoor significante statistische scheeftrekkingen worden geëlimineerd.

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;

De resultaten

Ik heb dit uitgevoerd op een Windows 8 VM, met 8 GB RAM en 4 vCPU's, met SQL Server 2012 (11.02376). Hier zijn resultaten in tabelvorm, gesorteerd op gemiddelde duur, snelste eerst:

En hier is een grafische weergave van de gemiddelde duur: