另类随机读大表数据

想到写这个存储过程,是由于做频道首页的时候,需要从表中取随机的N行记录。
但由于表比较大,十几万条记录,如果再用order by newid()这样的方式从数据库
读取数据,本身order by 就慢,再加上newid(),就慢上加慢。
后来想了很久,决定用随机从数据库中随机取一页数据的方式。虽然做不到离散方式
的随机,虽然是集中式的,但也是随机地取数据了。

我做的分页是写在程序里的,当然,放在程序里和作为一个存储过程,有好有坏,在这里,
我就不作专门的请讨论。

注意事项:
1.一定要对排序字段建索引,建与不建索引,速度的差别是很大的。
2.由于之前分布在程序中进行,现在这个分布存储过程,只用于随机取数据
所以还没有经过太多的测试。
下面是存储过程脚本
Code:

/*----------------------------
Author     :Nick.Liu
CreatedDate:2008-12-23
CopyRight:http://www.dreampea.com //使用请保留这里
功能:
1.实现查询分页功能
2.随机读取一页数据
输入参数说明:
@Source :数据源,可以是一个查询语句
@PageSize:一页大小,-1为查询所有页,-2为查询随机页
@RowIDOrderString :排序规则 格式:字段名 desc/asc
@CurrentPageIndex :当前页,由1开始

输出:
表1:当前页数据
表2:@Source 的行数
修改记录:

-----------------------------*/
CREATE Proc [dbo].[Proc_Pager]
@Source nvarchar(1000)
,@PageSize int
,@RowIDOrderString nvarchar(200)
,@CurrentPageIndex int

as
DECLARE @SQLString nvarchar(500);
declare @SqlQuery nvarchar(2000)
DECLARE @ParmDefinition nvarchar(500);
DECLARE @QueryParmDefinition nvarchar(500);
DECLARE @CountOut varchar(30);

SET @SQLString = N'SELECT @Count = count(1)
   FROM ('+@Source+') a'
SET @ParmDefinition = N'@Count int OUTPUT';
SET @QueryParmDefinition = N'@BeginIndexInner bigint,@EndIndexInner bigint';

EXECUTE sp_executesql @SQLString, @ParmDefinition, @Count=@CountOut OUTPUT;
declare @Pages int
set @Pages = @CountOut/@PageSize
if @CurrentPageIndex = -2
Begin
set @CurrentPageIndex = cast(@Pages*Rand() as int)
End

declare @BeginIndex  bigint
declare @EndIndex  bigint

set @BeginIndex = @PageSize*(@CurrentPageIndex-1)
set @EndIndex = @PageSize*@CurrentPageIndex

set @SqlQuery = 'select RowCnt,* from
                        (
                            select ROW_NUMBER() OVER(order by '+@RowIDOrderString+') as RowCnt
                            ,* from ('+@Source+') a
                        )a'
    if(@CurrentPageIndex != -1)
    Begin
             set @SqlQuery = @SqlQuery+ ' where RowCnt > @BeginIndexInner
                        and RowCnt <=@EndIndexInner'
    End
print @sqlQuery
EXECUTE sp_executesql @SqlQuery,@QueryParmDefinition,@BeginIndexInner= @BeginIndex,@EndIndexInner= @EndIndex
exec('select RowCnt=count(1) from ('+@Source+') a')
posted @ 2009-05-01 18:33  文刀无尽  阅读(250)  评论(2)    收藏  举报