在项目中,我们经常遇到或用到分页,那么在大数据量(百万级以上)下,哪种分页算法效率最优呢?我们不妨用事实说话。
测试环境
硬件:CPU 酷睿双核T5750 内存:2G
软件:Windows server 2003 + Sql server 2005
OK,我们首先创建一数据库:data_Test,并在此数据库中创建一表:tb_TestTable
然后我们在数据表中插入2000000条数据:
我首先写了五个常用存储过程:
1,利用select top 和select not in进行分页,具体代码如下:
从测试结果来看,使用2分法确实可以提高效率并使效率更为稳定,我又增加了第159999页的测试,用时仅296ms,效果相当的不错!
下面是2分法使用select max的代码,已相当完善。
1
3
--
/*----- 对数据进行了2分处理使查询前半部分数据与查询后半部分数据性能相同 -------*/
4
5
alter
PROCEDURE
proc_paged_2part_selectMax
6
(
7
@tblName
nvarchar
(
200
),
--
--要显示的表或多个表的连接
8
@fldName
nvarchar
(
500
)
=
'
*
'
,
--
--要显示的字段列表
9
@pageSize
int
=
10
,
--
--每页显示的记录个数
10
@page
int
=
1
,
--
--要显示那一页的记录
11
@fldSort
nvarchar
(
200
)
=
null
,
--
--排序字段列表或条件
12
@Sort
bit
=
0
,
--
--排序方法,0为升序,1为降序(如果是多字段排列Sort指代最后一个排序字段的排列顺序(最后一个排序字段不加排序标记)--程序传参如:' SortA Asc,SortB Desc,SortC ')
13
@strCondition
nvarchar
(
1000
)
=
null
,
--
--查询条件,不需where
14
@ID
nvarchar
(
150
),
--
--主表的主键
15
@Dist
bit
=
0
,
--
--是否添加查询字段的 DISTINCT 默认0不添加/1添加
16
@pageCount
int
=
1
output,
--
--查询结果分页后的总页数
17
@Counts
int
=
1
output
--
--查询到的记录数
18
)
19
AS
20
SET
NOCOUNT
ON
21
Declare
@sqlTmp
nvarchar
(
1000
)
--
--存放动态生成的SQL语句
22
Declare
@strTmp
nvarchar
(
1000
)
--
--存放取得查询结果总数的查询语句
23
Declare
@strID
nvarchar
(
1000
)
--
--存放取得查询开头或结尾ID的查询语句
24
25
Declare
@strSortType
nvarchar
(
10
)
--
--数据排序规则A
26
Declare
@strFSortType
nvarchar
(
10
)
--
--数据排序规则B
27
28
Declare
@SqlSelect
nvarchar
(
50
)
--
--对含有DISTINCT的查询进行SQL构造
29
Declare
@SqlCounts
nvarchar
(
50
)
--
--对含有DISTINCT的总数查询进行SQL构造
30
31
declare
@timediff
datetime
--
耗时测试时间差
32
select
@timediff
=
getdate
()
33

34
if
@Dist
=
0
35
begin
36
set
@SqlSelect
=
'
select
'
37
set
@SqlCounts
=
'
Count(*)
'
38
end
39
else
40
begin
41
set
@SqlSelect
=
'
select distinct
'
42
set
@SqlCounts
=
'
Count(DISTINCT
'
+
@ID
+
'
)
'
43
end
44

45

46
if
@Sort
=
0
47
begin
48
set
@strFSortType
=
'
ASC
'
49
set
@strSortType
=
'
DESC
'
50
end
51
else
52
begin
53
set
@strFSortType
=
'
DESC
'
54
set
@strSortType
=
'
ASC
'
55
end
56

57

58

59
--
------生成查询语句--------
60
--
此处@strTmp为取得查询结果数量的语句
61
if
@strCondition
is
null
or
@strCondition
=
''
--
没有设置显示条件
62
begin
63
set
@sqlTmp
=
@fldName
+
'
From
'
+
@tblName
64
set
@strTmp
=
@SqlSelect
+
'
@Counts=
'
+
@SqlCounts
+
'
FROM
'
+
@tblName
65
set
@strID
=
'
From
'
+
@tblName
66
end
67
else
68
begin
69
set
@sqlTmp
=
+
@fldName
+
'
From
'
+
@tblName
+
'
where (1>0)
'
+
@strCondition
70
set
@strTmp
=
@SqlSelect
+
'
@Counts=
'
+
@SqlCounts
+
'
FROM
'
+
@tblName
+
'
where (1>0)
'
+
@strCondition
71
set
@strID
=
'
From
'
+
@tblName
+
'
where (1>0)
'
+
@strCondition
72
end
73

74
--
--取得查询结果总数量-----
75
exec
sp_executesql
@strTmp
,N
'
@Counts int out
'
,
@Counts
out
76
declare
@tmpCounts
int
77
if
@Counts
=
0
78
set
@tmpCounts
=
1
79
else
80
set
@tmpCounts
=
@Counts
81

82
--
取得分页总数
83
set
@pageCount
=
(
@tmpCounts
+
@pageSize
-
1
)
/
@pageSize
84

85
/**/
/*
*当前页大于总页数 取最后一页*
*/
86
if
@page
>
@pageCount
87
set
@page
=
@pageCount
88

89
--
/*-----数据分页2分处理-------*/
90
declare
@pageIndex
int
--
总数/页大小
91
declare
@lastcount
int
--
总数%页大小
92
93
set
@pageIndex
=
@tmpCounts
/
@pageSize
94
set
@lastcount
=
@tmpCounts
%
@pageSize
95
if
@lastcount
>
0
96
set
@pageIndex
=
@pageIndex
+
1
97
else
98
set
@lastcount
=
@pagesize
99

100
--
//***显示分页
101
if
@strCondition
is
null
or
@strCondition
=
''
--
没有设置显示条件
102
begin
103
if
@pageIndex
<
2
or
@page
<=
@pageIndex
/
2
+
@pageIndex
%
2
--
前半部分数据处理
104
begin
105
if
@page
=
1
106
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
107
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
108
else
109
begin
110
if
@Sort
=
1
111
begin
112
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
113
+
'
where
'
+
@ID
+
'
<(select min(
'
+
@ID
+
'
) from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
1
)
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
114
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
+
'
) AS TBMinID)
'
115
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
116
end
117
else
118
begin
119
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
120
+
'
where
'
+
@ID
+
'
>(select max(
'
+
@ID
+
'
) from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
1
)
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
121
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
+
'
) AS TBMinID)
'
122
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
123
end
124
end
125
end
126
else
127
begin
128
set
@page
=
@pageIndex
-
@page
+
1
--
后半部分数据处理
129
if
@page
<=
1
--
最后一页数据显示
130
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@lastcount
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
131
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
132
else
133
if
@Sort
=
1
134
begin
135
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
136
+
'
where
'
+
@ID
+
'
>(select max(
'
+
@ID
+
'
) from(
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
2
)
+
@lastcount
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
137
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TBMaxID)
'
138
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
139
end
140
else
141
begin
142
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
143
+
'
where
'
+
@ID
+
'
<(select min(
'
+
@ID
+
'
) from(
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
2
)
+
@lastcount
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
144
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TBMaxID)
'
145
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
146
end
147
end
148
end
149

150
else
--
有查询条件
151
begin
152
if
@pageIndex
<
2
or
@page
<=
@pageIndex
/
2
+
@pageIndex
%
2
--
前半部分数据处理
153
begin
154
if
@page
=
1
155
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
156
+
'
where 1=1
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
157
else
if
(
@Sort
=
1
)
158
begin
159
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
160
+
'
where
'
+
@ID
+
'
<(select min(
'
+
@ID
+
'
) from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
1
)
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
161
+
'
where (1=1)
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
+
'
) AS TBMinID)
'
162
+
'
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
163
end
164
else
165
begin
166
set
@strTmp
=
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
167
+
'
where
'
+
@ID
+
'
>(select max(
'
+
@ID
+
'
) from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
1
)
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
168
+
'
where (1=1)
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
+
'
) AS TBMinID)
'
169
+
'
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
170
end
171
end
172
else
173
begin
174
set
@page
=
@pageIndex
-
@page
+
1
--
后半部分数据处理
175
if
@page
<=
1
--
最后一页数据显示
176
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@lastcount
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
177
+
'
where (1=1)
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
178
else
if
(
@Sort
=
1
)
179
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
180
+
'
where
'
+
@ID
+
'
>(select max(
'
+
@ID
+
'
) from(
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
2
)
+
@lastcount
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
181
+
'
where (1=1)
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TBMaxID)
'
182
+
'
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
183
else
184
set
@strTmp
=
@SqlSelect
+
'
* from (
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
as
VARCHAR
(
4
))
+
'
'
+
@fldName
+
'
from
'
+
@tblName
185
+
'
where
'
+
@ID
+
'
<(select min(
'
+
@ID
+
'
) from(
'
+
@SqlSelect
+
'
top
'
+
CAST
(
@pageSize
*
(
@page
-
2
)
+
@lastcount
as
Varchar
(
20
))
+
'
'
+
@ID
+
'
from
'
+
@tblName
186
+
'
where (1=1)
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TBMaxID)
'
187
+
'
'
+
@strCondition
+
'
order by
'
+
@fldSort
+
'
'
+
@strSortType
+
'
) AS TempTB
'
+
'
order by
'
+
@fldSort
+
'
'
+
@strFSortType
188
end
189
end
190

191
--
----返回查询结果-----
192
exec
sp_executesql
@strTmp
193
select
datediff
(ms,
@timediff
,
getdate
())
as
耗时
194
--
print @strTmp
195
SET
NOCOUNT
OFF
196
GO
197
执行示例:exec proc_paged_2part_selectMax 'tb_testTable','ID,userName,userPWD,userEmail',10,100000,'ID',0,null,'ID',0
这种测试只在单机进行,并且没有在实际开发WEB项目中分页测试,测试项也比较单一,所以不够全面系统,但从其效率相比上,我们可以在数据库分页算法上进行有效的控制。
2,利用select top 和 select max(列键)
3,利用select top和中间变量--此方法因网上有人说效果最佳,所以贴出来一同测试
4,利用Row_number() 此方法为SQL server 2005中新的方法,利用Row_number()给数据行加上索引
5,利用临时表及Row_number
1
create
procedure
proc_CTE
--
利用临时表及Row_number
2
(
3
@pageIndex
int
,
--
页索引
4
@pageSize
int
--
页记录数
5
)
6
as
7
set
nocount
on
;
8
declare
@ctestr
nvarchar
(
400
)
9
declare
@strSql
nvarchar
(
400
)
10
declare
@datediff
datetime
11
begin
12
select
@datediff
=
GetDate
()
13
set
@ctestr
=
'
with Table_CTE as
14
(select ceiling((Row_number() over(order by ID ASC))/
'
+
str
(
@pageSize
)
+
'
) as page_num,* from tb_TestTable)
'
;
15
set
@strSql
=
@ctestr
+
'
select * From Table_CTE where page_num=
'
+
str
(
@pageIndex
)
16
end
17
begin
18
execute
sp_executesql
@strSql
19
select
datediff
(ms,
@datediff
,
GetDate
())
20
set
nocount
off
;
21
end
22
OK,至此,存储过程创建完毕,我们分别在每页10条数据的情况下在第2页,第1000页,第10000页,第100000页,第199999页进行测试,耗时单位:ms 每页测试5次取其平均值
存过 |
第2页耗时 |
第1000页耗时 |
第10000页耗时 |
第100000页耗时 |
第199999页耗时 |
效率排行 |
1用not in |
0ms |
16ms |
47ms |
475ms |
953ms |
3 |
2用select max |
5ms |
16ms |
35ms |
325ms |
623ms |
1 |
3中间变量 |
966ms |
970ms |
960ms |
945ms |
933ms |
5 |
4row_number |
0ms |
0ms |
34ms |
365ms |
710ms |
2 |
4临时表 |
780ms |
796ms |
798ms |
780ms |
805ms |
4 |
测试结果显示:select max >row_number>not in>临时表>中间变量
于是我对效率最高的select max方法用2分法进行了扩展,代码取自互联网,我修改了ASC排序时取不到值的BUG,测试结果:
2分法 |
156ms |
156ms |
180ms |
470ms |
156ms |
1* |
分享到:
相关推荐
总结,ASP.NET SQL存储过程分页是一个重要的数据库查询优化技术,它结合了存储过程的高效性和分页的实用性。通过创建合适的存储过程,正确配置ASP.NET的控件,以及处理好分页事件,我们可以构建出高效且用户友好的...
当我们谈论“SQL高效存储过程分页”时,我们主要关注如何利用存储过程来实现数据库查询的分页效果,这在大数据量的场景下尤为重要,因为直接查询所有数据可能会导致性能下降,甚至阻塞数据库服务。 分页是Web应用...
以下是一个通用的分页存储过程示例,适用于SQL Server 2000: ```sql CREATE PROCEDURE Pagination @tblName varchar(255), @strGetFields varchar(1000) = '*', @fldName varchar(255)='', @PageSize int = 10...
### 最简单的SQL Server数据库存储过程分页 #### 知识点概述 在处理大量数据时,分页查询是一项常见的需求。传统的T-SQL分页方法可能会导致性能问题,尤其是在面对百万级别的数据集时。本文介绍一种简单且高效的...
此外,对于大数据量的场景,我们还可以考虑使用索引视图、分区函数等高级技术来优化分页性能。但这些方法需要结合具体的数据结构和查询模式来设计,以确保最佳效果。 在SQL Server 2005和2010中,由于不支持`OFFSET...
### SQL Server 存储过程实现分页查询 #### 背景介绍 在数据库操作中,分页查询是非常常见的需求之一。特别是在数据量较大的场景下,分页不仅可以提高查询效率,还能改善用户体验。SQL Server 提供了多种方式进行...
### SQL存储过程分页技术详解 在数据库管理与应用程序开发中,数据的高效查询与展示是至关重要的。尤其是在处理大量数据时,分页查询能够显著提高数据加载速度和用户体验。SQL存储过程作为一种预编译的代码块,可以...
综上所述,"经典的分页、排序SQL 通用存储过程"旨在解决数据库查询中的性能挑战,通过创建存储过程实现灵活、高效的分页和排序。这样的存储过程不仅可以应用于MySQL,其他支持存储过程的数据库系统,如SQL Server、...
### 速度最快SQL分页存储过程详解 #### 概述 在数据库操作中,分页查询是一种非常常见的需求。为了提高查询效率并优化用户体验,设计一个高效、灵活且易于使用的分页存储过程变得尤为重要。本文将详细介绍一个被...
### C#调用SQL存储过程实现分页功能详解 在.NET框架中,使用C#语言进行数据库操作是非常常见的。本文将详细介绍如何通过C#来调用SQL Server中的存储过程,并实现分页功能。这对于提高ASP.NET应用程序的性能、增强...
本话题将深入探讨如何利用SQL存储过程实现高效的分页功能,并针对亿万级的数据量进行优化。 在处理大数据量时,传统的SQL分页方法,如使用`LIMIT`或`OFFSET`,可能会遇到性能问题,因为它们需要扫描大量的行来找到...
通过对存储过程的逻辑分析,我们可以看出它充分考虑了性能优化的需求,例如通过先查询总记录数再进行分页查询的方式避免了不必要的数据加载,提高了查询效率。此外,通过参数化的设置也增加了查询的灵活性和通用性。
本示例介绍了一个名为`pr_GetDataListByPage`的存储过程,该过程通过动态SQL实现了基于参数化的分页查询功能。下面将详细解析此存储过程的设计思路及实现细节。 ##### 参数说明 - **@TableName**:指定表名。 - **...
本教程重点讲解了如何利用.NET、Java和SQL进行存储过程分页,这是一种在数据库级别实现分页的方法,可以显著提高查询效率。 首先,让我们了解一下什么是存储过程。存储过程是预编译的SQL语句集合,存储在数据库...
值得注意的是,优化分页性能不仅要考虑存储过程的设计,还要关注索引的使用。合理的索引可以显著提高分页查询的速度,尤其是在处理大量数据时。同时,避免全表扫描,尽可能利用覆盖索引来减少I/O操作,也是提升性能...
总结,通用的存储过程SQL分页查询语句是数据库开发中的重要工具,它结合了存储过程的复用性和SQL的灵活性,可以高效地处理大数据量的分页查询。通过选择适当的分页方法和优化策略,我们可以进一步提升查询性能,提供...
本文将详细介绍如何使用存储过程实现SQL Server的分页,并演示如何在代码中调用这些存储过程。 一、分页的基本原理 分页通常涉及到两个关键参数:每页大小(PageSize)和当前页码(CurrentPage)。通过这两个参数...
ASP.NET 存储过程分页是一种在Web应用中实现高效数据检索的技术,它结合了数据库存储过程和分页策略,以提高性能并减轻服务器负担。在这个主题中,我们将深入探讨如何在ASP.NET环境中利用存储过程来实现数据的分页...
根据给定的SQL Server存储过程代码片段,我们可以深入解析与SQL Server中的`GROUP BY`分组查询、存储过程以及分页技术相关的知识点。 ### SQL Server中的`GROUP BY`分组查询 `GROUP BY`子句在SQL查询语言中用于将...