У меня есть две таблицы, в которые мы добавляем около 100 тыс. и 1,5 млн новых строк каждый день. Это записи журнала, и в более чем 99% случаев меня интересуют последние 3 рабочих дня при чтении.
Если я запускаю простой запрос, например
SELECT
0 as Id, ProcessElementName, Null as ModelPath, Status, Remark, ValidFrom, Application, JobID, JobName, CreateDate, CreatedBy, MessageType, Running, Manual, Environment, RunIdentifier, BatchJobGroup, BatchJob, IsTemp, TotalRows = COUNT(*) OVER()
FROM dbo.pclTB_ProcessElementInfo WITH (NOLOCK)
WHERE
ValidFrom > '6/26/2017 12:00:00 AM'
AND ValidFrom <= '6/26/2017 11:59:59 PM'
AND (Environment in ('---')) AND
(
Remark LIKE '%' + 'btve' + '%'
AND Application = '---'
AND (IsTemp = 0 OR IsTemp IS NULL )
AND ProcessElementName = '---'
)
ORDER BY JobID ASC
OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY
это может занять до 10 секунд. В других запросах есть несколько объединений, но большинство из них простые. Когда я обновляю статистику вручную, время выполнения сокращается примерно до 2 секунд, но я уверен, что еще есть возможности для улучшения (я знаю о флаге трассировки 2371).
Как лучше всего оптимизировать таблицу (или запрос?) для получения самых последних строк? Может быть, имеет смысл создать новую таблицу только с записями за последние X дней?
Изменить: это индекс, используемый для запроса выше.
CREATE NONCLUSTERED INDEX [IX_ProcessElementNameApplicationEnvironmentValidFrom] ON [dbo].[pclTB_ProcessElementInfo]
(
[ProcessElementName] ASC,
[Application] ASC,
[Environment] ASC,
[ValidFrom] ASC
)
INCLUDE (
[Status],
[Remark],
[JobID],
[JobName],
[CreateDate],
[CreatedBy],
[MessageType],
[Running],
[Manual],
[RunIdentifier],
[BatchJobGroup],
[BatchJob],
[IsTemp]
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
WITH (NOLOCK)
. Не для повышения производительности, а как лучшая практика. Кроме того, не могли бы вы добавить план выполнения? - person Evaldas Buinauskas   schedule 28.06.2017Remark LIKE '%' + 'btve' + '%'
иAND (IsTemp = 0 OR IsTemp IS NULL )
- убийцы. Я бы посоветовал изменить структуру вашей таблицы, чтобыIsTemp
был столбцом, не допускающим значение NULL, и заменить NULL на 0. Затем вы можете создать отфильтрованный индекс с условиемIsTemp = 0
. - person Evaldas Buinauskas   schedule 28.06.2017isTemp
в качестве первого столбца в индексе. И, как упомянул Эвалдас, убийца здесь, вероятно, замечает что-то вроде этого. Возможно, поместите этот столбец в индекс, а не включайте его в столбцы. Я не вижу здесь другой возможности. - person Marek Vitek   schedule 28.06.2017OR
условия обычно медленные. Имея столбец, не допускающий значения NULL, вы сможете изменить свой индекс с условием, которое я дал в предыдущем комментарии. Это уменьшит количество строк, которые вам нужно прочитать. - person Evaldas Buinauskas   schedule 28.06.2017