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

Trimmzeit von datetime – ein Follow-up

Im Anschluss an meinen vorherigen Beitrag über das Trimmen der Zeit von Datum und Uhrzeit war ich angespornt, die Leistungsmerkmale verschiedener Methoden ohne Datenzugriff klarer zu demonstrieren. Im ursprünglichen Beitrag habe ich schnell sieben verschiedene Methoden zum unabhängigen Konvertieren eines datetime-Werts in ein Datum verglichen, gezeigt, dass die Unterschiede vernachlässigbar waren, und dann direkt zur Analyse der Verwendung dieser Methoden in tatsächlichen Abfragen übergegangen, die Daten zurückgeben.

In diesem Beitrag wollte ich mehrere verschiedene Wege zeigen, um die Zeit von der Datumszeit zu kürzen (tatsächlich 18 verschiedene Wege!), ohne tatsächliche Daten einzuführen, um zu sehen, ob wir einen "schnellsten" Weg zur Durchführung dieser Aufgabe verkünden können.

Die Methoden

Hier sind die 18 Methoden, die ich testen würde, einige aus dem Blogpost, auf den Madhivanan nach meinem vorherigen Post hingewiesen hat:

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

Der Test

Ich habe eine Schleife erstellt, in der ich jede Konvertierung 1.000.000 Mal ausführen und dann den Vorgang für alle 18 Konvertierungsmethoden 10 Mal wiederholen würde. Dadurch würden Messwerte für 10.000.000 Conversions für jede Methode bereitgestellt, wodurch signifikante statistische Verzerrungen beseitigt würden.

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;

Die Ergebnisse

Ich habe dies auf einer Windows 8-VM mit 8 GB RAM und 4 vCPUs ausgeführt, auf der SQL Server 2012 (11.0.2376) ausgeführt wird. Hier sind tabellarische Ergebnisse, sortiert nach durchschnittlicher Dauer, schnellste zuerst:

Und hier ist eine grafische Darstellung der durchschnittlichen Dauer: