如何提高SQL Server 2008中的大表分页速度
问题描述:
我有一个名为Users
的表,其中有1000万条记录。这是表结构:如何提高SQL Server 2008中的大表分页速度
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.
任何人给我一些建议如何提高呼叫速度会升值。谢谢!
答
这看起来好像不会改变它的工作方式或进行某种预先计算。
用于查找页面上的UserId
S上的指数是窄,因为它可以(叶子页面将包含只是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页?
+0
:谢谢你的帮助! – user441222
我想你在强调执行计划中的错误。这就是说,聚集索引查找占用了你85%的时间。这里发生了什么?你还可以得到一些io统计数据,看看是否有任何锁争用? –
@jtseng - 有趣的观察,但这只是成本模型的限制。对于具有1000万行的'CREATE TABLE T1(C INT PRIMARY KEY);'。 SQL Server提供的行数在100和120之间,行数在9700000和9700020之间,估计成本完全相同[见计划](http://i.stack.imgur.com/jYodX.png),尽管第二个必须处理比第一个更多的行。它假定扫描只需要100行,而不是实际的9,700,020,因此计划的这一部分显示的成本不正确。 [脚本重现](http://pastebin.com/FUS0JL8e) –