sql >> Databáze >  >> RDS >> Database

Oříznutí času od data a času – pokračování

V návaznosti na můj předchozí příspěvek o ořezávání času od datetime jsem byl pobídnut k jasnějšímu demonstrování výkonnostních charakteristik různých metod bez nutnosti přístupu k datům. V původním příspěvku jsem rychle porovnal sedm různých metod převodu hodnoty datetime na datum nezávisle, ukázal jsem, že rozdíly byly zanedbatelné, a pak jsem se rovnou přesunul k analýze použití těchto metod ve skutečných dotazech, které vracejí data.

V tomto příspěvku jsem chtěl ukázat několik různých způsobů, jak oříznout čas od data a času (ve skutečnosti 18 různými způsoby!), aniž bych uváděl jakákoli skutečná data, abych zjistil, zda bychom mohli prohlásit "nejrychlejší" způsob provedení tohoto úkolu.

Metody

Zde je 18 metod, které bych testoval, některé jsou převzaty z blogového příspěvku, na který Madhivanan poukázal po mém předchozím příspěvku:

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

Test

Vytvořil jsem smyčku, kde bych každou konverzi spustil 1 000 000krát a poté 10krát opakoval proces pro všech 18 metod převodu. To by poskytlo metriky pro 10 000 000 konverzí pro každou metodu, čímž by se eliminovalo jakékoli významné statistické zkreslení.

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;

Výsledky

Spustil jsem to na virtuálním počítači Windows 8 s 8 GB RAM a 4 vCPU se systémem SQL Server 2012 (11.0.2376). Zde jsou tabulkové výsledky seřazené podle průměrné doby trvání, nejdříve od nejrychlejšího:

A zde je grafické znázornění průměrné doby trvání: