首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

2008年 最新海量数据分页解决方法

2012-03-05 
2008年 最新海量数据分页看了很多海量数据分页,大都都是单表的,而且当数据增大时效率下降但是排序的列不能

2008年 最新海量数据分页
看了很多海量数据分页,大都都是单表的,而且当数据增大时效率下降但是排序的列不能有重复值,而在sql 2005 里通过 OVER子句可以解决,不过它也只是在后台把查询结果加一列,然后所有数据查一遍,每条记录插入序号,当有上千万数据时效率也是有点低的。
所以我归纳了下,如果排序的列有重复,就用sql2005 的存储过程,否则用我写的存储过程
sql 2005的存储过程:
create PROCEDURE [dbo].[SP_Common_PageChange]
@sql nvarchar(4000), --sql字符串
@OrderString nvarchar(100),
@PageIndex int,
@PageSize int,
@RecordCount int OUT,
@PageCount int OUT
AS
/*计算页面数据*/
Declare @PageIndex1 int
declare @sqlRecordCount nvarchar(4000)
Set @PageIndex1=@PageIndex+1;
set @sqlRecordCount ='select @RecordCount=count(*) from ('+@sql+') mxf'
/*获取记录数*/
EXEC sp_executesql @sqlRecordCount,N'@RecordCount int OUTPUT',@RecordCount OUTPUT--计算总页数
SET @PageCount = CEILING(@RecordCount * 1.0 / @PageSize)
SET @sql='('+@sql+') h'
/* 基于SQL SERVER 2005 */
SET @sql=N'select SerialNumber,* from (select *,row_number() over (order by '+@OrderString+')'
+'as serialnumber from '+@sql+') as T where T.SerialNumber > ( '+convert(nvarchar(100),@PageIndex)+' * '+ convert(nvarchar(100),@PageSize)+' ) and'
+' T.SerialNumber <= ( '+convert(nvarchar(100),@PageIndex1)+' * '+convert(nvarchar(100),@PageSize)+' )'
EXEC (@sql)

本人写的存储过程:
请查看 http://new.qzone.qq.com/34065028


[解决办法]
MARK.
[解决办法]
不过怎么说 取900到1000条数据 始终是要取前1000条的
[解决办法]
关注,学习!
[解决办法]
mar
[解决办法]
学习
[解决办法]

海量数据的分页始终都是一个难题。
[解决办法]
晕,我写的存储过程 可以不用
[解决办法]
[u][/u]

探讨
学习

[解决办法]
探讨

海量数据的分页始终都是一个难题。

[解决办法]
learn
[解决办法]
本人写的存储过程:

由于比通用的改进了一些,所以要复杂些。。

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

-- 多表之间用逗号分开, 条件不带where 但是 要加括号确保万一
-- 多表一定要带条件,如果是单表字段前可不加表,排序字段不可有重复列
Create procedure [dbo].[USP_DWX_SqlDataPaging]
@tbNameS varchar(255), --表名
@tbFields varchar(1000), --返回字段 字段前加所属表,
@OrderField varchar(255), --排序的字段名,此字段不能有重复值 前面不用加表
@PageSize int, --页尺寸
@PageIndex int, --页码 0 or 1 表示 首页, -1 表示尾页
@OrderType bit, --排序类型,1是升序,0是降序
@strWhere varchar(1500), -- 查询条件 字段前加所属表,
@Total int output , --返回总记录数
@OrderValue varchar(20) = '', --排序字段上一次页最大或最小值
-- 在@OrderValue不为空的情况下使用下面条件
@OrderFieldType char(1) = 'S', --排序字段类型,"S" 字符串,"I" 整型
@PageDirection bit = 1 --点击页的方向,1是下一页,0是上一页
as
declare @strSql varchar(5000) --主语句
declare @strOrder varchar(200) --排序
declare @strSqlCount nvarchar(500)--查询记录总数主语句
declare @strtemp varchar(500) --排序附加语句
declare @strWhereSql varchar(200) --带where 条件
declare @strOrderIn varchar(200) --内查询排序
if RTRIM(LTRIM(@strWhere)) !='' 
set @strWhereSql = ' where '+ @strWhere
else
set @strWhereSql = ''
--------------总记录数---------------
set @strSqlCount='Select @TotalCout=count(*) from ' + @tbNameS + @strWhereSql


--------------排序-----------------0是降序,1未升序
set @Total=0 
set @strOrderIn = ''
if @OrderType !=0
begin
set @strOrder='order by ' + @OrderField + ' asc '
end
else
begin
set @strOrder='order by '+ @OrderField + ' desc'
end

if RTRIM(LTRIM(@OrderValue)) = '' --传统分页
begin
-- -- 去掉前面的表
-- declare @tmpOrderField varchar(255)
-- set @tmpOrderField = @OrderField
-- set @tmpOrderField = REVERSE(@tmpOrderField);
-- set @tmpOrderField = SUBSTRING(@tmpOrderField,0,CHARINDEX('.',@tmpOrderField))
-- set @tmpOrderField = REVERSE(@tmpOrderField);
if @OrderType !=0
begin
set @strtemp= '>(select max(' + ' ' +@OrderField+ ') from (select top '
+str((@PageIndex-1)*@PageSize) + ' '+@OrderField +' from '+@tbNameS
+ @strWhereSql+ ' '+ @strOrder +') as tb)'
end
else
begin
set @strtemp= '<(select min('+ ' ' +@OrderField+ ') from (select top '
+str((@PageIndex-1)*@PageSize) + ' '+@OrderField +' from '+@tbNameS
+ @strWhereSql+ ' '+ @strOrder +') as tb)'
end
  
end
else
begin -- 根据 提供的比较值

declare @oper char(3) 
set @oper = ''
if @PageDirection = 1
begin
if @OrderType != 0 -- desc 降序
begin
set @oper = ' > '
end
else
set @oper = ' < '
end
else
begin
if @OrderType !=0 -- desc 降序
begin
set @oper = ' < '
set @strOrderin = 'order by ' + @OrderField + ' desc '
end
else
begin
set @oper = ' > '
set @strOrderin = 'order by ' + @OrderField + ' asc '
end
end;
if @OrderFieldType = 'S'
begin
set @strtemp= @oper + +''''+ @OrderValue +'''';
end
else
set @strtemp= @oper + @OrderValue--cast(@OrderValue as int);
  
end
--------------分页为第一页------------
if @PageIndex =1 or @PageIndex =0
begin
set @PageIndex =1
set @strSql = 'Select top ' +str(@PageSize)+ ' ' + @tbFields + ' from '+ @tbNameS + @strWhereSql+ ' ' + @strOrder
end
else if @PageIndex = -1 --最后一页
begin
if @OrderType !=0
begin
set @strOrderIn='order by ' + @OrderField + ' desc '
end
else
begin
set @strOrderIn='order by '+ @OrderField + ' asc'
end
  
set @strSql = 'Select top ' +str(@PageSize)+ ' ' + @tbFields + ' from '+ @tbNameS + @strWhereSql + ' ' + @strOrderIn
set @strSql = 'Select * from (' + @strSql + ' ) t '+ @strOrder;
end
else 
begin
declare @temp varchar(200)
set @temp = ''
if RTRIM(LTRIM(@strWhere)) != ''
set @temp = ' and ' + @strWhere
  
if if RTRIM(LTRIM(@OrderValue)) = ''
set @strSql = 'Select top ' +str(@PageSize) + ' ' + @tbFields 
+' from ' + @tbNameS + ' where '+@OrderField +' '
+ @strtemp + ' ' + @temp + @strOrder
else
begin
set @strSql = 'Select top ' +str(@PageSize) + ' ' + @tbFields 
+' from ' + @tbNameS + ' where '+@OrderField +' '
+ @strtemp + ' ' + @temp + @strOrderIn
set @strSql = 'select * from(' + @strSql + ') tb ' + @strOrder
end
end
exec sp_executesql @strSqlCount,N'@TotalCout int output',@Total output
exec(@strSql)

[解决办法]
@OrderValue varchar(20) = '', --排序字段上一次页最大或最小值
当 @OrderValue 不为空时,查询900到1000的数据 不用查询前900条,直接根据这个@OrderValue值就可以了。
[解决办法]
我个人不喜欢所谓“通用”的分页存储过程
分页需要通盘考虑取出来的字段的类型,排序字段是否可以保证唯一。你做的优化前提之一就是要有唯一的排序字段,结合业务逻辑考虑,这个排序字段可能包含多个,那你的@orderValue参数该怎么传?



我认为分页存储过程只应该有一个通用的写法.
有唯一排序字段,该怎么写/没有唯一排序字段,该怎么写. 类似这样
[解决办法]
再也不要写什么千万级的分页存储过程.
客户需要的内容 最好确定在一页 或者 几页.
几千万条数据分页展现给用户,你想他在里面淘金啊.
[解决办法]

探讨
再也不要写什么千万级的分页存储过程.
客户需要的内容 最好确定在一页 或者 几页.
几千万条数据分页展现给用户,你想他在里面淘金啊.

[解决办法]
学习

[解决办法]
学习!
[解决办法]
rownumber
[解决办法]
正需要这个,关注

热点排行