Suite à mon article précédent sur la réduction du temps à partir de la date et de l'heure, j'ai été incité à démontrer plus clairement les caractéristiques de performance de diverses méthodes sans impliquer l'accès aux données. Dans le message d'origine, j'ai rapidement comparé sept méthodes différentes de conversion d'une valeur datetime en une date indépendamment, j'ai montré que les différences étaient négligeables, puis je suis passé directement à l'analyse de l'utilisation de ces méthodes dans les requêtes réelles qui renvoient des données.
Dans cet article, je voulais montrer plusieurs façons différentes de réduire l'heure à partir de la date et de l'heure (18 façons différentes en fait !), Sans introduire de données réelles, pour voir si nous pouvions proclamer un moyen "le plus rapide" d'effectuer cette tâche.
Les méthodes
Voici les 18 méthodes que je testerais, certaines tirées du billet de blog que Madhivanan a signalé après mon précédent billet :
DECLARE @d DATETIME, @ds DATETIME = SYSDATETIME();
L'épreuve
J'ai créé une boucle dans laquelle j'exécuterais chaque conversion 1 000 000 fois, puis je répéterais le processus pour les 18 méthodes de conversion 10 fois. Cela fournirait des mesures pour 10 000 000 conversions pour chaque méthode, éliminant ainsi toute distorsion statistique importante.
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;
Les résultats
J'ai exécuté ceci sur une machine virtuelle Windows 8, avec 8 Go de RAM et 4 vCPU, exécutant SQL Server 2012 (11.0.2376). Voici les résultats sous forme de tableau, triés par durée moyenne, le plus rapide en premier :
Et voici une représentation graphique de la durée moyenne :