2014-11-29 3 views
1

У меня есть две таблицы:SQL: странное поведение производительности запросов

  • Nodes - действительно маленький столик, около 20 строк
  • Events - довольно большой стол, около 10M строк

и после запроса :

select 
    e.DeviceAlias as Mac, n.NodeId, n.city as City, n.street as Street, e.Status, 
    CASE WHEN e.Status = 'U' THEN 'Unknown' ELSE 'Known' END as 'Source', 
    COUNT (*) as 'Count', 
    SUM(CASE WHEN e.SentMessageId > 0 THEN 1 ELSE 0 END) as SentMsgCount 
from 
    events e 
join 
    Nodes n on e.NodeId = n.NodeId 
where 
    e.InsertDate >= @startdate 
    and e.InsertDate <= @enddate 
group by 
    e.DeviceAlias, e.Status, n.NodeId, n.city, n.street 

Запрос выполняется более 5 минут. У меня есть все необходимые индексы, и советник sql perf не предлагает никаких дополнительных индексов или статистики. Однако, если я избавлюсь от соединения и выполним следующий запрос:

select 
    e.DeviceAlias as Alias, NodeId, 
    CASE WHEN e.Status = 'U' THEN 'Unknown' ELSE 'Known' END as 'Source', 
    COUNT (*) as 'Count', 
    SUM(CASE WHEN e.SentMessageId > 0 THEN 1 ELSE 0 END) as SentMsgCount 
from 
    events e 
where 
    e.InsertDate >= '2014-07-01' 
    and e.InsertDate <= '2014-11-28' 
group by 
    e.DeviceAlias,nodeid, e.Status 

он выполняет в течение 30 секунд.

Простым решением является использование второго запроса и заполнение остальных данных из таблицы узлов в коде C#.

Но это меня беспокоит, почему соединение с таким маленьким столом дает эту огромную производительность? Есть ли способ лучше?

+0

Вы действительно хотите выполнить 5 минут или 5 минут, чтобы вернуть весь результат запроса клиенту? Можете ли вы попробовать обернуть запрос чем-то вроде SELECT COUNT (*) FROM (...) T и посмотреть, продолжает ли он выполняться в течение 5 минут? – CrimsonKing

+0

У вас есть актуальная статистика? – erikkallen

+0

Я выполняю оба запроса от студии управления. Насколько мне известно, он отображает время выполнения запроса и возвращает результат. В любом случае второй запрос выполняется за 30 секунд, тогда как объем данных почти одинаковый (ровно столько же строк) – Marcin

ответ

0

erikkallen, вы мой мужчина;) Обновление статистики сократило время выполнения до 38 секунд! В любом случае - WTF ?? У меня была статистика автоматического обновления, установленная на true в этой базе данных ... Таблица событий растет очень быстро, поэтому autoupdate должен выполняться каждые несколько часов в соответствии с «Таблица имеет более 500 строк, и есть увеличение на 500 + 20% от размер таблицы с момента последнего обновления »(от http://www.pythian.com/blog/sql-server-statistics-maintenance-and-best-practices/)

1

Посмотрите на план объяснения: SQL Server (если моя память обслуживает меня правильно) может использовать алгоритмы вложенного цикла, хэша или слияния: если в плане появляется Nested Loop (что я сомневаюсь), тогда база данных будет выглядеть in - ie loop through - небольшая таблица для каждой из миллионов строк в более крупной таблице, по одному циклу для каждой «родительской» строки. Если используется merge, тогда должно быть меньше циклов, но, скорее всего, данные будут предварительно отсортированы. Для присоединения Хэша внешний набор может «искать» соответствующую строку из хеш-таблицы.

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

Смежные вопросы