Следвайки предишната ми публикация за изрязване на времето от datetime, бях подтикнат да демонстрирам по-ясно характеристиките на производителността на различни методи, без да включвам достъп до данни. В оригиналната публикация бързо сравних седем различни метода за независимо преобразуване на стойност за дата и време в дата, показах, че разликите са незначителни, след което преминах направо към анализиране на използването на тези методи в реални заявки, които връщат данни.
В тази публикация исках да покажа няколко различни начина за отрязване на времето от дата и време (всъщност 18 различни начина!), без да въвеждам реални данни, за да видя дали можем да обявим „най-бърз“ начин за изпълнение на тази задача.
Методите
Ето 18-те метода, които бих тествал, някои взети от публикацията в блога, която Мадхиванан посочи след предишната ми публикация:
DECLARE @d DATETIME, @ds DATETIME = SYSDATETIME();
Тестът
Създадох цикъл, в който ще стартирам всяко преобразуване 1 000 000 пъти и след това ще повторя процеса за всичките 18 метода за преобразуване 10 пъти. Това ще осигури показатели за 10 000 000 реализации за всеки метод, елиминирайки всякакво значително статистическо изкривяване.
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;
Резултатите
Пуснах това на Windows 8 VM, с 8 GB RAM и 4 vCPU, работещ със SQL Server 2012 (11.0.2376). Ето таблични резултати, сортирани по средна продължителност, първо най-бързият:
А ето и графично представяне на средната продължителност: