我有一个名为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.
任何人都会给我一些关于如何提高分页速度的建议。谢谢!
答案 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页吗?