У меня есть несколько больших (~ миллиард строк, ~ 100 ГБ) архивных таблиц с журналами поведения клиентов для аналитических целей (еще нет хранилища, в процессе разработки).
Каждый заполняется один раз в день из таблицы ежедневных журналов и содержит данные за текущий год.
вне ежедневных вставок эти таблицы никогда не изменяются, выбираются только из
ежедневные журналы располагаются в порядке столбца servertime
, который может работать как первичный ключ, однако он не используется ни для какого запроса, кроме ежедневной вставки,
- все запросы ограничены диапазонами столбца
datetime
. Эти два столбца примерно одинаковы примерно в 90% времени, в остальное время они могут быть разнесены даже на несколько дней, servertime
отмечает при отправке пакета журналов (поэтому они обычно сортируются по возрастанию в плоских файлах), а datetime
- это фактическое время создания журнала, которое может оставаться в кэше несколько дней.
Многие запросы требуют запросов с разными значениями, как в приведенном ниже запросе, для различных диапазонов времени (от часа к месяцу). , 3 месяца, последний квартал, текущий год), поэтому мы держим текущий год в одном месте, но количество строк начало становиться смешным.
SELECT
CAST(datetime as date),
element,
COUNT(DISTINCT client_id),
COUNT(DISTINCT session_id),
COUNT(*)
FROM dbo.pageviews
WHERE DATETIME >= ''
AND DATETIME < ''
GROUP BY CAST(DATETIME as date), element
В других случаях нам приходится тянуть все журналы для данногоclient_id
или session_id
в течение заданного периода.
У нас была некоторая устаревшая индексация (некластеризованная с несколькими включенными столбцами, с индексами, кратными размеру таблиц).
IЯ пытаюсь немного улучшить ситуацию, пока мы ждем склад, поэтому я начал вносить некоторые базовые изменения.
Вопрос 1:
Я добавил кластерd индексировать по столбцу datetime
(для справки по запросам) и некластеризовать по servetime
(для облегчения ежедневных вставок). Это правильно или должно быть наоборот?
Вопрос 2:
Если бы мы разбили таблицы, скажем, на ежемесячные порции и выполнили запросы по отношению кСМОТРИТЕ со всеми их как UNION ALL
и datetime
как кластеризованный индекс, было бы полезно, если бы мы часто вычисляли COUNT(distinct X)
по периодам, которые охватывали бы несколько таких таблиц?
Любые другие исправления, которые могли бы помочь управлять этимв краткосрочной перспективе?
Контрольный пример: Я проверил запрос, как указано выше, с трехмесячным периодом с различной индексацией и получил следующие результаты:
- нет индексов вообще - ~ 38 минут
- кластеризованный индекс для
datetime
- ~ 34 минуты - некластеризованный индекс для
datetime
с include
для всех соответствующих столбцов - ~ 34минут
РЕДАКТИРОВАТЬ: Дополнительная информация:
В последнее время 33% времени servertime
больше datetime
, datetime
такжепод влиянием изменений часового пояса, летом он падает до 18% (GMT + 2 / GMT + 1)
Существует небольшое, но не незначительное количество журналов, загруженных с datetime
намного, намного раньше, чем текущая временная метка, иногда даже месяцы. Это приемлемо с нашей точки зрения отчетности, но может оказать существенное влияние на кластеризованный индекс более datetime
, если он продолжит добавлять новые строки назад.