2014-09-22 2 views
2

У меня есть ниже запрос для поддержки работника нумерацией страниц сортируются по имени сотрудникаНастройка производительности этого запроса?

SELECT rowNumAlias 
    ,Employee.employeeId 
    ,Employee.NAME 
FROM (
    SELECT row_number() OVER (
      ORDER BY Employee.NAME ASC 
      ) rowNumAlias 
     ,employeeId 
     ,NAME 
    FROM Employee 
    ) employeeData 
INNER JOIN Employee ON Employee.employeeId = employeeData.employeeId 
WHERE rowNumAlias BETWEEN ? AND ? 

Где rowNumAlias ​​параметр может быть любое целое число от 1 до 100

Этот запрос занимает около 7 секунд на моей базе данных SQL Server, имеющий 1 миллион записей. Есть ли способ минимизировать время выполнения запроса?

+0

Вам необходимо [получить план выполнения] (http://stackoverflow.com/questions/7359702/how-do-i-obtain-a-query-execution-plan). Это скажет вам, что является самой медленной частью запроса и, возможно, даже предложит индексы, которые можно использовать для ускорения запроса. – Justin

+0

Какая версия SQL Server? Если вы находитесь в 2012 году, есть еще лучшие способы сделать разбивку на страницы. Что скажет вам план выполнения запроса? Может быть, вам не хватает индекса (например, для Employee.name)? – jpw

+0

Предполагая, что индексы pk/fk индексируются, заказ на имя сотрудника, вероятно, будет хитом производительности, а не «оптимизировать». значит, у него есть индекс? (или использовать синтаксис синтаксиса SQL Server 2012 лучше, если он доступен) –

ответ

1

Вы можете попробовать так:

SELECT * FROM (
SELECT (SELECT row_number() OVER (ORDER BY e2.NAME ASC) FROM Employee e2 WHERE Employee.employeeId = E2.employeeId) rowNumAlias, 
    ,Employee.employeeId 
    ,Employee.NAME 
FROM Employee 
) e3 WHERE e3.rowNumAlias BETWEEN ? AND ? 
+0

вы уверены, что хотите предложить run_number() как коррелированный подзапрос в предложении select? не уверен, что он даже будет работать –

+0

Я не знаю, есть ли другое решение для этого запроса. – Iulian

+0

но как ваше предложение улучшит существующее? если вы не уверены, что я бы посоветовал не пытаться иначе, вы получите «downvoted» –

1

Вы можете попробовать использовать КТР для этого.

;WITH employeeData as 
(
    SELECT row_number() OVER (ORDER BY Employee.NAME ASC) rowNumAlias, 
    employeeId, 
    NAME 
    FROM Employee 
) 
SELECT employeeData.rowNumAlias, 
employeeData.employeeId, 
employeeData.NAME 
FROM employeeData 
INNER JOIN Employee ON Employee.employeeId = employeeData.employeeId 
WHERE rowNumAlias BETWEEN ? AND ? 
+0

Это хорошее предложение, но это также взяло такое же время исполнения – user3198603

+0

почти такие же результаты – user3198603

1

Если вы на SQL Server 2012+ можно использовать синтаксис ORDER BY ... OFFSET ... FETCH ... сделать нумерацию страниц:

SELECT EmployeeId, Name  
FROM Employee 
ORDER BY Employee.Name ASC OFFSET ? ROWS FETCH NEXT ? ROWS ONLY 

OFFSET определяет, сколько строк пропустить и FETCH NEXT сколько получить. См. documentation.

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

;With cte (rownum, employeeid, name) as (
    SELECT 
     rownum = row_number() OVER (ORDER BY employee.name ASC), 
     employeeid, 
     name 
    FROM employee 
) 

SELECT rownum, employeeid, name 
FROM cte 
WHERE rownum BETWEEN ? AND ?; 
+0

почти такие же результаты – user3198603

+0

@ user3198603 Это странно. Мои планы выполнения показывают, что мой запрос cte имеет стоимость (относительно партии) 33% по сравнению с принятым ответом, стоимость которого (относительно партии) составляет 67%. Вы пробовали его с некластеризованным индексом для employee.name по возрастанию? – jpw

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