Самый быстрый запрос SQL для неиндексированных данных - PullRequest
1 голос
/ 10 ноября 2010

Я создаю несколько пользовательских отчетов для базы данных SQL Server 2005. База данных принадлежит стороннему управляющему приложению. Данные, которые я извлекаю, не относятся к основным целям сайта, поэтому данные в основном не индексируются, за исключением столбца меток времени. На данный момент задействована только одна таблица - таблица из 700 миллионов строк. Поэтому, когда я запускаю запрос к нему, который должен вернуть только 50 строк, он должен опрашивать все 700 миллионов.

Я хочу ускорить это, но не хочу индексировать каждый столбец, который добавляю в предложение WHERE - я не знаю, что добавление такого количества индексов приведет к значительному повышению скорости ( или я не прав?). Поэтому мне любопытно, что было бы лучше, если бы я не смог добавить какие-либо новые индексы в таблицу!

Хранимая процедура не выглядит наилучшим образом. Индексированное представление может быть лучшей идеей? Мысли?

Вот схема таблицы:

DeviceGuid (PK, uniqueidentifier, not null)
DeviceID (int, not null)
WindowsEventID (PK, int, not null) (indexed)
EventLog (varchar(64), not null)
EventSource (varchar(64), not null)
EventID (int, not null)
Severity (int, not null)
Description (nvarchar(max), not null)
TimeOfEvent (PK, datetime, not null) (indexed)
OccurrenceNbr (int, not null)

Вот пример запроса:

SELECT COUNT(*) AS NumOcc, EventID, EventLog, EventSource, Severity, TimeOfEvent, Description
FROM WindowsEvent
WHERE DeviceID='34818'
    AND Severity=1
    AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM')
    AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM')
    AND EventID<>34113
    AND EventID<>34114
    AND EventID<>34112
    AND EventID<>57755
    AND EventSource<>'AutoImportSvc.exe'
    AND EventLog='Application'
GROUP BY EventID, EventLog, EventSource, Severity, Description
ORDER BY NumOcc DESC

Может быть, запрос отстой ... он возвращает 53 строки за 4,5 минуты.

Ответы [ 4 ]

0 голосов
/ 15 июля 2016

Это довольно просто, но я бы попробовал индексированное значение в качестве первого теста в

0 голосов
/ 10 ноября 2010

попробуйте этот метод, используя двойной трюк row_number:

SELECT  RN_Desc as NumOcc, *
FROM    (
        SELECT  row_number() Over(partition by EventId order by EventLog, EventSource, Severity, Description) as RN_Asc,
                row_number() Over(partition by EventId order by EventLog desc, EventSource desc, Severity desc, Description desc) as RN_Desc,
                *
        FROM    WindowsEvent 
        WHERE   DeviceID='34818' 
                AND Severity=1 
                AND TimeOfEvent >= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/10/27 12:00:00 AM') 
                AND TimeOfEvent <= DATEADD(hh, DATEDIFF(hh, GETDATE(), GETUTCDATE()), '2010/11/3 12:00:00 AM') 
                AND EventID<>34113 
                AND EventID<>34114 
                AND EventID<>34112 
                AND EventID<>57755 
                AND EventSource<>'AutoImportSvc.exe' 
                AND EventLog='Application' 
        ) t
WHERE   RN_Asc = 1 
ORDER BY NumOcc DESC 

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

0 голосов
/ 17 марта 2011

Окончательное решение здесь состояло в том, чтобы выполнить запрос к индексированным полям, а затем отфильтровать их в приложении, выполняющем запрос.Два поля содержали достаточно схожую информацию, которую я мог запросить по одному индексу и получить очень близкое приближение к нужным данным.Я перебрал и удалил все несоответствующие объекты из списка результатов.Взял НАМНОГО меньше времени!

0 голосов
/ 10 ноября 2010

Если ваш запрос не использует индексы, это будет очень плохо. Вам не нужен индекс для каждого столбца, но вам нужен индекс в правом столбце. Учитывая, что TimeOfEvent уже проиндексирован, он может не подойти для ваших нужд.

Правильный столбец будет зависеть от распределения ваших данных. Наилучшим индексом, вероятно, будет индекс, обеспечивающий максимальную селективность (т. Е. Когда вы знаете ключевое значение индекса, он возвращает наименьшее количество строк). Если вам известен столбец, обеспечивающий наилучшую селективность, попробуйте индекс по нему.

Чтобы помочь определить наилучший индекс, вы можете использовать Просмотр оценочного плана выполнения в SSMS. Это поможет вам увидеть, какой индекс будет использоваться. После добавления индекса вы можете выполнить запрос и оценить результаты с помощью плана выполнения. И, конечно, наблюдение истекшего времени тоже поможет.

...