SQL Server 2008 三种经典分页方法与性能比较
本文详解 SQL Server 中基于旧版本的三种经典数据分页方案:利用 Not IN 与 SELECT TOP、基于主键 ID 的查找以及使用游标存储过程。通过对 2万条测试数据的分析,明确指出第二种“ID大于最大值”的方法效率最高,而游标方案虽慢但通用性最强,并给出相应的优化建议。
结果或目标
在 SQL Server 2008 及更早版本中,由于缺少 OFFSET/FETCH 等现代语法,开发者常需借助特定技巧实现数据分页。不同的实现方式在查询效率和代码复杂度上存在显著差异。本文将通过对比三种常见方案的执行表现,帮助确定在实际开发中最合适的分页策略。
准备条件
为了直观展示不同方案的性能差异,首先建立包含两万个测试记录的数据库表并填充数据。以下代码将创建 TestTable 并批量插入数据:
CREATE TABLE [TestTable] (
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[FirstName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
[LastName] [nvarchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,
[Country] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Note] [nvarchar] (2000) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT TestTable ON
declare @i int
set @i=1
while @i<=20000
begin
insert into TestTable([id], FirstName, LastName, Country,Note) values(@i, 'FirstName_XXX','LastName_XXX','Country_XXX','Note_XXX')
set @i=@i+1
end
SET IDENTITY_INSERT TestTable OFF
真实操作顺序
第1步:采用 Not In 结合 Top 进行分页
目的:利用子查询排除前 N 页的数据,选取剩余部分的最新记录。
原理:先查询出前 N 页的所有 ID 存入集合,外层查询时排除这些 ID,再用 Top 限制返回行数。
-- 假设每页显示 10 条,当前为第 3 页(即跳过前 20 条)
SELECT TOP 10 *
FROM TestTable
WHERE (ID NOT IN
(SELECT TOP 20 id
FROM TestTable
ORDER BY id))
ORDER BY ID
注意:当数据量极大且连续翻页时,NOT IN 子句中的内层查询会变得越来越长,导致扫描范围增加,性能呈下降趋势。
第2步:利用 ID 大于多少配合 Top 分页
目的:通过定位上一页最后一条记录的 ID 值,精准截取下一页的数据。这是公认相对高效的纯 SQL 写法。
入口:需要一个排序好的数据集,通常基于主键或自增 ID。
-- 获取第 3 页(每页 10 条,跳过前 20 条)
SELECT TOP 10 *
FROM TestTable
WHERE (ID >
(SELECT MAX(id)
FROM (SELECT TOP 20 id
FROM TestTable
ORDER BY id) AS T))
ORDER BY ID
完成判断:此方法只需查询少量的 ID 来确定边界,减少了全表扫描的范围,因此比第一种方案更快。
第3步:利用 SQL 游标存储过程分页
目的:封装复杂逻辑,提供通用的分页接口,尤其适用于查询语句极其复杂的场景。
重要参数:@sqlstr(查询字符串)、@currentpage(当前页码)、@pagesize(每页行数)。
create procedure XiaoZhengGe
@sqlstr nvarchar(4000), --查询字符串
@currentpage int, --第N页
@pagesize int --每页行数
as
set nocount on
declare @P1 int, --P1是游标的id
@rowcount int
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
set @currentpage=(@currentpage-1)*@pagesize+1
exec sp_cursorfetch @P1,16,@currentpage,@pagesize
exec sp_cursorclose @P1
set nocount off
完成判断与排错
性能评估结论:
1. **效率最高**:分页方案二(利用 ID 大于多少和 SELECT TOP)。该方案在执行计划中对索引的利用率最好,尤其在数据量较大时优势明显。缺点是必须拼接 SQL 字符串作为输入参数较为繁琐。
2. **效率次之**:分页方案一(Not In 方案)。逻辑简单易懂,但随着页面数向后推移,子查询数据量增加,拖慢响应速度。
3. **效率最差但最通用**:分页方案三(游标存储过程)。虽然游标机制在处理海量数据时性能较低,但对于带有复杂关联、动态生成的查询语句,它能提供稳定的分页支持。
优化建议:
对于没有主键的表,可以使用临时表辅助分页,或者沿用方案三的游标方式。无论使用哪种方案,务必确保 ID 字段或其他排序字段建立了正确的索引,这能成倍提升查询效率。
简要总结
在 SQL Server 2008 环境下,选择分页方案需权衡业务需求。对于常规的主键排序查询,优先推荐拼接 SQL 的“ID大于最大值”方案以获得最佳性能;若查询结构多变且对极致性能要求不高,则可选用游标存储过程以保证兼容性。以上就是 SQL Server 2008 中三种分页方法与比较的详细内容,更多关于 SQL 性能优化的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













