如何提高SQL Server 2008中的大表分页速度

时间:2013-06-29 16:13:53

标签: sql-server sql-server-2008 sql-server-performance

我有一个名为Users的表,其中有1000万条记录。这是表结构:

CREATE TABLE [dbo].[Users](
    [UsersID] [int] IDENTITY(100000,1) NOT NULL,
    [LoginUsersName] [nvarchar](50) NOT NULL,
    [LoginUsersPwd] [nvarchar](50) NOT NULL,
    [Email] [nvarchar](80) NOT NULL,
    [IsEnable] [int] NOT NULL,
    [CreateTime] [datetime] NOT NULL,
    [LastLoginTime] [datetime] NOT NULL,
    [LastLoginIp] [nvarchar](50) NOT NULL,
    [UpdateTime] [datetime] NOT NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
(
    [UsersID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

我在UpdateTime列上有一个非聚集索引。

分页sql:

;WITH UserCTE AS (
   SELECT * FROM 
    (SELECT 
        ROW_NUMBER() OVER (ORDER BY UpdateTime DESC) AS row,UsersID as rec_id -- select primary key only
    FROM 
        dbo.Users WITH (NOLOCK)
    ) A WHERE row BETWEEN 9700000 AND 9700020
)
SELECT
   *
FROM
    dbo.Users WITH (NOLOCK) WHERE UsersID IN (SELECT UserCTE.rec_id FROM UserCTE)

上面的查询:

SQL Server parse and compile time: 
CPU time = 0 ms, elapsed time = 3 ms.
(21 row(s) affected)

SQL Server Execution Times:
CPU time = 2574 ms,  elapsed time = 3549 ms.

enter image description here

任何人都会给我一些关于如何提高分页速度的建议。谢谢!

1 个答案:

答案 0 :(得分:3)

在不改变其工作方式或进行某种预先计算的情况下,它看起来一样好。

用于在页面上找到UserId的索引尽可能地缩小(叶页将仅包含UpdateTime和聚集索引键UsersID。您可以通过更改为datetime2使索引稍微缩小,但这不会产生显着差异。此外,您可以检查此索引是否没有过多的碎片。

如果您有一个UpdateTimeOrder的索引顺序整数列,那么您可以执行

SELECT *
FROM dbo.Users
WHERE UpdateTimeOrder BETWEEN 9700000 AND 9700020

但是维护这样一个列以及并发INSERTS / UPDATES / DELETES将很困难。一个更容易但效果不太好的预先计算是创建一个索引视图。

CREATE VIEW dbo.UserCount
WITH SCHEMABINDING
AS
SELECT COUNT_BIG(*) AS Count
FROM [dbo].[Users]

GO

CREATE UNIQUE CLUSTERED INDEX IX ON dbo.UserCount(Count)

然后检索预先计算的计数并使用ROW_NUMBER() OVER (ORDER BY UpdateTime ASC)调用另一个查询,如果在索引中间查找超过一半的行(并从当前计数中减去原始行数)

但为什么你真的需要这个呢?你真的让人们访问485,000页吗?