2014-09-22 57 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数据库中有100万条记录。 有没有一种方法可以最大限度地减少查询执行时间?

+0

你需要[得到执行计划](http://stackoverflow.com/questions/7359702/how-do-i-obtain-a-query-execution-plan)。这会告诉你查询的最慢部分是什么,甚至可能会建议可以用来加快查询的索引。 – Justin 2014-09-22 10:11:26

+0

哪个版本的SQL Server?如果你在2012年以上,有更好的方法来做分页。查询执行计划告诉你什么?也许你错过了一个索引(例如Employee.name)? – jpw 2014-09-22 10:13:17

+0

假设pk/fk被索引,对员工姓名的排序很可能是性能问题,没有其他“优化”。所以它的名字有一个索引? (或者使用sql server 2012更好的分页语法(如果可用)) – 2014-09-22 10:20:32

回答

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

是否确定要在select子句中建议将row_number()作为相关子查询运行?不知道它会甚至工作 – 2014-09-22 10:23:51

+0

我不知道这个查询是否有其他解决方案。 – Iulian 2014-09-22 10:28:04

+0

但您的提案如何改进现有?如果你不确定我会建议不要尝试,否则你会得到“downvoted” – 2014-09-22 10:33:03

1

你可以尝试使用CTE这一点。

;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 2014-09-23 10:29:45

+0

几乎相同的结果 – user3198603 2014-09-26 12:49:34

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 2014-09-26 12:49:09

+0

@ user3198603这很奇怪。我的执行计划显示,与已接受的答案相比,我的cte查询的成本(相对于批次)为33%,而成本(相对于批次)为67%。您是否尝试使用nonclustered index for employee.name升序? – jpw 2014-09-26 13:07:23