Database
 sql >> Baza danych >  >> RDS >> Database

Czas przycinania od datetime – kontynuacja

Kontynuując mój poprzedni post o przycinaniu czasu od daty do czasu, zostałem zachęcony do wyraźniejszego zademonstrowania charakterystyki wydajności różnych metod bez angażowania dostępu do danych. W oryginalnym poście szybko porównałem siedem różnych metod niezależnej konwersji wartości daty i godziny na datę, pokazałem, że różnice są nieistotne, a następnie od razu przeszedłem do analizy użycia tych metod w rzeczywistych zapytaniach zwracających dane.

W tym poście chciałem pokazać kilka różnych sposobów przycinania czasu od daty do czasu (18 różnych sposobów!), bez wprowadzania żadnych rzeczywistych danych, aby zobaczyć, czy możemy ogłosić „najszybszy” sposób wykonania tego zadania.

Metody

Oto 18 metod, które testowałbym, niektóre zaczerpnięte z wpisu na blogu, który Madhivanan wskazał po moim poprzednim poście:

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

Test

Stworzyłem pętlę, w której uruchomiłbym każdą konwersję 1 000 000 razy, a następnie powtórzyłem proces dla wszystkich 18 metod konwersji 10 razy. Zapewniłoby to metryki dla 10 000 000 konwersji dla każdej metody, eliminując wszelkie znaczące odchylenia statystyczne.

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;

Wyniki

Uruchomiłem to na maszynie wirtualnej z systemem Windows 8, z 8 GB pamięci RAM i 4 procesorami wirtualnymi, z systemem SQL Server 2012 (11.0.2376). Oto wyniki tabelaryczne, posortowane według średniego czasu trwania, od najszybszego:

A oto graficzna reprezentacja średniego czasu trwania: