2012-04-10 1 views
5

В Scaling Up Your Data Warehouse with SQL Server 2008 R2 автор рекомендует использовать ключ целочисленной даты в формате YYYYMMDD в качестве кластерного индекса в ваших таблицах фактов, чтобы оптимизировать скорость запроса.TSQL DateTime to DateKey Int

Каков наилучший способ преобразования ключевого поля даты в ключ даты? Я чувствую, что следующий будет работать, но немного неаккуратно:

select Replace(CONVERT(varchar,GETDATE(),102),'.','') 

Очевидно, что я не использую GETDATE, а столбец даты в таблице, которая будет использовать в своих агрегатах.

Во-первых, как бы вы предложили сделать это преобразование? Является ли моя идея приемлемой?

Во-вторых, у кого был большой успех с использованием ключа даты в виде кластеризованного индекса?

ответ

8

ISO длинный (112) будет делать трюк:

SELECT CONVERT(INT, CONVERT(VARCHAR(8), GETDATE(), 112)) 

Casting GetDate() прямо в целое с ISO 112 дает 41008 по какой-то причине, но идущий через VARCHAR, кажется, работает - я буду обновлять если я думаю о более быстром броске.

EDIT: В отношении к междунар только против VarChar дискуссии, вот мои выводы (повторяемый на моем тестовом стенде & производство сервера) метод Varchar использует меньше времени центрального процессора на полмиллиона забросов, но фракция медленнее в целом - ничтожна если ваше дело с миллиардами строк

EDIT 2: Пересмотренный тестом случае, чтобы очистить кэш и даты различных

DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT YEAR([Date]) * 10000 + MONTH([Date]) * 100 + DAY([Date]) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 218 ms, elapsed time = 255ms.  
DBCC FREEPROCCACHE; 
DBCC DROPCLEANBUFFERS; 
SET STATISTICS TIME ON; 
WITH RawDates ([Date]) 
      AS (SELECT TOP 500000 
         DATEADD(DAY, N, GETDATE()) 
       FROM  TALLY 
      ) 
    SELECT CONVERT(INT, CONVERT(VARCHAR(8), [Date], 112)) 
    FROM RawDates 
SET STATISTICS TIME OFF 

(500000 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 266 ms, elapsed time = 602ms 
+1

преобразования GETDATE() прямо в INT с IS 112 дает 41008, потому что это количество дней с даты 0. Вы можете проверить, сравнив этот результат с результатом DATEDIFF между 0 и GETDATE(). 'SELECT CONVERT (INT, GETDATE(), 112), DATEDIFF (день, 0, GETDATE())' –

+0

@AdamPorad +1 Приветствия, поясняющие, что – HeavenCore

+1

Я думаю, что ваш тест испорчен. Разница в прошедшем времени является результатом отображения длинного списка значений на экране.Кроме того, вы используете GetDate(), поэтому SQL Server распознает его как константу и фактически не выполняет вычисления для каждой строки. Вам нужно использовать столбец из фактической таблицы. Наконец, для точной проверки производительности вам необходимо удалить чистые буферы и освободить кеш процедур. Вы не должны делать это на производственном сервере. –

2

Преобразование в строки и обратно может быть на удивлении медленно , Вместо этого, вы могли бы иметь дело исключительно с целыми числами, например:

Select Year(GetDate()) * 10000 + Month(GetDate()) * 100 + Day(GetDate()) 

В моем кратком тестировании, это немного быстрее, чем преобразование в строку, а затем в целом. Функция Year, Month и Day возвращает целое число, поэтому производительность немного лучше.

4

Вместо того, чтобы создавать DateKey с использованием формата YYYYMMDD, вы можете использовать функцию DATEDIFF, чтобы получить количество дней между 0 (то есть «датой, представленной 0»), и датой, в которой вы создаете DateKey.

SELECT DATEDIFF(day,0,GETDATE()) 

Недостаток заключается в том, что вы не можете легко проверить значение и определить дату, но вы можете использовать функцию DATEADD рассчитать первоначальную дату (я также видел этот трюк используется обрезает часть времени даты и времени).

SELECT DATEADD(day, 41007, 0) 

(Примечание: 41007 является результатом функции DATEDIFF выше, когда я запустил его на 4/10/2012.)