Я работаю над некоторыми обновлениями внутренней системы веб-аналитики, которую мы предоставляем нашим клиентам (в отсутствие предпочтительного поставщика или Google Analytics), и я работаю над следующим запросом:
select
path as EntryPage,
count(Path) as [Count]
from
(
/* Sub-query 1 */
select
pv2.path
from
pageviews pv2
inner join
(
/* Sub-query 2 */
select
pv1.sessionid,
min(pv1.created) as created
from
pageviews pv1
inner join Sessions s1 on pv1.SessionID = s1.SessionID
inner join Visitors v1 on s1.VisitorID = v1.VisitorID
where
pv1.Domain = isnull(@Domain, pv1.Domain) and
v1.Campaign = @Campaign
group by
pv1.sessionid
) t1 on pv2.sessionid = t1.sessionid and pv2.created = t1.created
) t2
group by
Path;
Я проверил этот запрос с 2 миллионами строк в таблице PageViews, и его запуск занимает около 20 секунд. Я заметил, что в плане выполнения дважды сканируется кластеризованный индекс, и оба раза он попадает в таблицу PageViews. В столбце Создано в этой таблице есть кластеризованный индекс.
Проблема в том, что в обоих случаях он повторяется по всем 2 миллионам строк, что, я считаю, является узким местом в производительности. Могу ли я что-нибудь сделать, чтобы предотвратить это, или я в значительной степени преуспел в том, что касается оптимизации?
Для справки, цель запроса - найти первый просмотр страницы для каждого сеанса.
РЕДАКТИРОВАТЬ: После большого разочарования, несмотря на полученную здесь помощь, я не смог заставить этот запрос работать. Поэтому я решил просто сохранить ссылку на страницу входа (и теперь страницу выхода) в таблице сеансов, что позволяет мне делать следующее:
select
pv.Path,
count(*)
from
PageViews pv
inner join Sessions s on pv.SessionID = s.SessionID
and pv.PageViewID = s.ExitPage
inner join Visitors v on s.VisitorID = v.VisitorID
where
(
@Domain is null or
pv.Domain = @Domain
) and
v.Campaign = @Campaign
group by pv.Path;
Этот запрос выполняется за 3 секунды или меньше. Теперь мне нужно либо обновить страницу входа / выхода в реальном времени, так как просмотры страниц записаны (оптимальное решение), либо запустить пакетное обновление с некоторым интервалом. В любом случае, это решает проблему, но не так, как я хотел.
Редактировать Редактировать: добавление отсутствующего индекса (после очистки с прошлой ночи) уменьшило запрос до нескольких миллисекунд). Woo Hoo!