sql >> Databasteknik >  >> RDS >> Database

Trimningstid från datetime – en uppföljning

Efter att ha följt upp mitt tidigare inlägg om trimningstid från datetime, blev jag sporrad att tydligare demonstrera prestandaegenskaperna för olika metoder utan att involvera dataåtkomst. I det ursprungliga inlägget jämförde jag snabbt sju olika metoder för att konvertera ett datetime-värde till ett datum oberoende, visade att skillnaderna var försumbara och gick sedan direkt till att analysera användningen av dessa metoder i faktiska frågor som returnerar data.

I det här inlägget ville jag visa flera olika sätt att trimma tiden från datetime (18 olika sätt faktiskt!), utan att introducera några faktiska data, för att se om vi kunde utropa ett "snabbaste" sätt att utföra denna uppgift.

Metoderna

Här är de 18 metoderna jag skulle testa, några hämtade från blogginlägget Madhivanan påpekade efter mitt tidigare inlägg:

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

Testet

Jag skapade en loop där jag skulle köra varje konvertering 1 000 000 gånger och sedan upprepa processen för alla 18 konverteringsmetoderna 10 gånger. Detta skulle ge mätvärden för 10 000 000 omvandlingar för varje metod, vilket eliminerar all signifikant statistisk skevhet.

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;

Resultaten

Jag körde detta på en Windows 8 VM, med 8 GB RAM och 4 vCPU:er, med SQL Server 2012 (11.0.2376). Här är resultat i tabellform, sorterade efter genomsnittlig varaktighet, snabbast först:

Och här är en grafisk representation av den genomsnittliga varaktigheten: