Оптимизация SQL-запросов (функция диапазона CTE +) в SQL Server 2005 - PullRequest
1 голос
/ 06 августа 2009

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

with Rec (Id,Name,ParentId)
as
(
    select Id,Name,ParentId from Departments where ParentId is null
    union all
    select d.Id, d.Name, d.ParentId from Departments d join Rec r on 
    (d.ParentId=r.Id)
)
select q.* from (
select ROW_NUMBER() OVER (ORDER BY r.Id DESC) AS [ROW_NUMBER], r.* from Rec r
) as q
where q.[ROW_NUMBER] between 100 and 200

То, что он делает, это иерархически опрашивает отделы-отступники, а затем выполняет ранжирование по нему.

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

Спасибо.

1 Ответ

1 голос
/ 06 августа 2009

Я уверен, что это могло бы быть немного лучше, учитывая следующие предположения:

  1. У вас есть правильный индекс по ParentId
  2. Вы извлекаете много данных (большинство столбцов) из таблицы

Что можно сделать: чтобы уменьшить нагрузку на подсистему io, мы можем сначала составить список идентификаторов, пролистать их (т.е. отфильтровать по RowNumber) и только после этого включить все остальные столбцы. Это эффективно приведет к работе с индексом по ParentId, который должен быть намного быстрее, учитывая два вышеупомянутых предположения.

Итак, вот мое предложение «лично», так сказать:

with Rec (Id,ParentId)
as
(
    select Id,ParentId from Departments where ParentId is null
    union all
    select d.Id, d.ParentId from Departments d join Rec r on 
    (d.ParentId=r.Id)
),
Paged 
as
(
    select * from (
        select ROW_NUMBER() OVER (ORDER BY r.Id DESC) AS [ROW_NUMBER], r.* from Rec r
    ) as q
    where q.[ROW_NUMBER] between 100 and 200
)
select * 
from 
    Paged
    inner join Departments d on d.Id = Paged.Id
...