30 миллионов записей. Разделите их на 24 часовых периода. Суммируйте их за один месяц. Промыть и повторить - PullRequest
5 голосов
/ 04 марта 2010

Мне нужно проверить 30 миллионов записей (на один месяц) ежедневных проверок билетов (Unix datetime) и разделить их на 24 часовых периода для 211 станций.

Сначала я создал представление, которое выбираетмесяц, который я ищу (и тип оборудования), затем создает значение Windows Datetime для каждого Unix datetime.

SELECT TOP (100) PERCENT StationName AS Station, MainTable.UnixDateTime AS ValTime, 
DATEADD(s, MainTable.UnixDateTime, CONVERT(DATETIME, '1970-01-01 00:00:00', 102)) AS WinTime
FROM  MainTable 
INNER JOIN StationName ON MainTable.StationID = StationName.StationID
WHERE (StationName.ValidStationCode = 32767) [use only valid stations] 
AND (MainTable. UnixDateTime >= 1264996800) 
AND (MainTable. UnixDateTime < 1267416000) 
AND (MainTable.EquipmentCode IN (33, 36)) [examine only this equipment]
ORDER BY Station

Затем я запускаю основную процедуру, которая использует оператор выбора в этом представлении для каждого изчасовые периоды.Это 24 оператора выбора для каждой из 211 станций.

Пример 1)

Update table Set [0102]= (select count(ValTime) 
from view 
where Station = @thisStation and DatePart (Hour, WinTime)>= 1 and DatePart (Hour, WinTime)< 2)
from view 
where table.Station = @thisStation

Пример 2)

Update table Set [0203]= (select count(ValTime) 
from view 
where Station = @thisStation and DatePart (Hour, WinTime)>= 2 and DatePart (Hour, WinTime)< 3) 
from view 
where table.Station = @thisStation

и т. Д.

Процедураработает - ууу!Это занимает 11 часов - Boo: (

Вывод например:

         0001 0102 0203 0304...2324
Station1   27  34   567  231... 123
Station2  245  57   23   198... 21
etc.

Выходная таблица имеет 25 столбцов.

Существует более быстрый и лучший способ сделать это, ноЯ не знаю, что это такое. (Купите суперкомпьютер?) Я думал о рангах и разделах, но не могу представить, как это будет работать. Есть какие-нибудь гуру?

Ответы [ 2 ]

3 голосов
/ 04 марта 2010

Unix времена хранятся в виде целых чисел. Я думаю, вы получите лучшую производительность, если будете обрабатывать их как целые числа вместо преобразования в DateTime. Например, чтобы получить час из даты в Unix, вы можете сделать это ...

Select (UnixDateTime % 86400) / 3600 As Hour

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

Select  StationName As Station,
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 0 Then MainTable.UnixDateTime End) As [0001],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 1 Then MainTable.UnixDateTime End) As [0102],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 2 Then MainTable.UnixDateTime End) As [0203],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 3 Then MainTable.UnixDateTime End) As [0304],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 4 Then MainTable.UnixDateTime End) As [0405],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 5 Then MainTable.UnixDateTime End) As [0506],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 6 Then MainTable.UnixDateTime End) As [0607],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 7 Then MainTable.UnixDateTime End) As [0708],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 8 Then MainTable.UnixDateTime End) As [0809],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 9 Then MainTable.UnixDateTime End) As [0910],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 10 Then MainTable.UnixDateTime End) As [1011],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 11 Then MainTable.UnixDateTime End) As [1112],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 12 Then MainTable.UnixDateTime End) As [1213],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 13 Then MainTable.UnixDateTime End) As [1314],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 14 Then MainTable.UnixDateTime End) As [1415],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 15 Then MainTable.UnixDateTime End) As [1516],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 16 Then MainTable.UnixDateTime End) As [1617],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 17 Then MainTable.UnixDateTime End) As [1718],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 18 Then MainTable.UnixDateTime End) As [1819],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 19 Then MainTable.UnixDateTime End) As [1920],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 20 Then MainTable.UnixDateTime End) As [2021],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 21 Then MainTable.UnixDateTime End) As [2122],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 22 Then MainTable.UnixDateTime End) As [2223],
        Count(Case When (MainTable.UnixDateTime % 86400) / 3600 = 23 Then MainTable.UnixDateTime End) As [2324]
FROM  MainTable 
INNER JOIN StationName ON MainTable.StationID = StationName.StationID
WHERE (StationName.ValidStationCode = 32767) --[use only valid stations] 
AND (MainTable.UnixDateTime >= 1264996800) 
AND (MainTable.UnixDateTime < 1267416000) 
AND (MainTable.EquipmentCode IN (33, 36)) --[examine only this equipment]
Group By StationName
ORDER BY Station
3 голосов
/ 04 марта 2010

Функция DatePart, вероятно, убивает вашу производительность. Я думаю, что это сильно ускорило бы разбивку даты на столбцы дня, часа и минуты. Добавьте индексы к этим столбцам, и вы сможете запрашивать буквальные значения, а не вычисленные значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...