我们的公司做一个分页查询,但是数据量过于庞大的话,尤其是到了40W甚至到了60W条记录以后。在页面跳转的时候就会出现客户体验过慢的问题(也就是从数据库抓信息过慢)。当时想了好几种方法:1.抓10页的数据,放到session中,然后在这10页中跳转没什么感觉,但是出了这10页就是问题了,还有就是如果用户对其中的数据进行修改了,另一个用户并不会及时得到修改的数据结果,因为他的数据也放在session中呢...2.就是最基本的分页技术,不用什么手段,但是抓取40W以后的数据也是一件麻烦事,有什么好的建议或者解决方案?大家集思广益一下!谢谢大家了!!!

解决方案 »

  1.   

    SQL 2005的ROW_NUMBER()实现分页功能DECLARE @pagenum AS INT, @pagesize AS INT
    SET @pagenum = 2
    SET @pagesize = 3
    SELECT *
    FROM (SELECT ROW_NUMBER() OVER(ORDER BY newsid DESC) AS rownum, 
            newsid, topic, ntime, hits
          FROM news) AS D
    WHERE rownum BETWEEN (@pagenum-1)*@pagesize+1 AND @pagenum*@pagesize
    ORDER BY newsid DESC aspx里面只需给SQL传入pageid和条数即可。 CSDN上还有个存储过程实现分页的代码: 
    ALTER PROCEDURE news_Showlist
    (
    @tblName   varchar(255),       -- 表名
    @strGetFields varchar(1000),  -- 需要返回的列
    @fldName varchar(255),      -- 排序的字段名
    @PageSize   int ,          -- 页尺寸
    @PageIndex  int ,           -- 页码
    @strWhere  varchar(1500),  -- 查询条件(注意: 不要加where)
    @Sort varchar(255)      --排序的方法)
    AS
    declare @strSQL   varchar(5000)       -- 主语句
    declare @strTmp   varchar(110)        -- 临时变量
    declare @strOrder varchar(400)        -- 排序类型if @Sort = 'desc'
    begin
    set @strTmp = '<(select min'
    set @strOrder = ' order by ' + @fldName +' desc'
    --如果@OrderType不是,就执行降序,这句很重要!
    end
    else
    begin
    set @strTmp = '>(select max'
    set @strOrder = ' order by ' + @fldName +' asc'
    end
     
    if @PageIndex = 1
    begin
    if @strWhere != ''   
      begin
    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from ' + @tblName 
    + ' where ' + @strWhere + ' ' + @strOrder
      end
    else
      begin
    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from '+ @tblName 
    + ' '+ @strOrder
      end
    --如果是第一页就执行以上代码,这样会加快执行速度
    end
    else
    begin
    --以下代码赋予了@strSQL以真正执行的SQL代码
    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from '
    + @tblName + ' where ' + @fldName + '' + @strTmp + '('+ @fldName + ') from 
    (select top ' + str((@PageIndex-1)*@PageSize) + ' '+ @fldName + ' from ' 
    + @tblName + '' + @strOrder + ') as tblTmp)'+ @strOrder
     
    if @strWhere != ''
    set @strSQL = 'select top ' + str(@PageSize) +' '+@strGetFields+ '  from '
    + @tblName + ' where ' + @fldName + '' + @strTmp + '('+ @fldName + ') from 
    (select top ' + str((@PageIndex-1)*@PageSize) + ' '+ @fldName + ' from '
     + @tblName + ' where ' + @strWhere + ' '+ @strOrder + ') as tblTmp) 
    and ' + @strWhere + ' ' + @strOrder
    end
    exec (@strSQL)
    RETURN 
      

  2.   

    --TOP n 实现的通用分页存储过程(转自邹建)
    CREATE PROC sp_PageView
    @tbname     sysname,            --要分页显示的表名
    @FieldKey   nvarchar(1000),   --用于定位记录的主键(惟一键)字段,可以是逗号分隔的多个字段
    @PageCurrent int=1,            --要显示的页码
    @PageSize   int=10,             --每页的大小(记录数)
    @FieldShow nvarchar(1000)='',   --以逗号分隔的要显示的字段列表,如果不指定,则显示所有字段
    @FieldOrder nvarchar(1000)='',   --以逗号分隔的排序字段列表,可以指定在字段后面指定DESC/ASC
                                              用于指定排序顺序
    @Where    nvarchar(1000)='',  --查询条件
    @PageCount int OUTPUT          --总页数
    AS
    SET NOCOUNT ON
    --检查对象是否有效
    IF OBJECT_ID(@tbname) IS NULL
    BEGIN
    RAISERROR(N'对象"%s"不存在',1,16,@tbname)
    RETURN
    END
    IF OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTable')=0
    AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsView')=0
    AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTableFunction')=0
    BEGIN
    RAISERROR(N'"%s"不是表、视图或者表值函数',1,16,@tbname)
    RETURN
    END--分页字段检查
    IF ISNULL(@FieldKey,N'')=''
    BEGIN
    RAISERROR(N'分页处理需要主键(或者惟一键)',1,16)
    RETURN
    END--其他参数检查及规范
    IF ISNULL(@PageCurrent,0)<1 SET @PageCurrent=1
    IF ISNULL(@PageSize,0)<1 SET @PageSize=10
    IF ISNULL(@FieldShow,N'')=N'' SET @FieldShow=N'*'
    IF ISNULL(@FieldOrder,N'')=N''
    SET @FieldOrder=N''
    ELSE
    SET @FieldOrder=N'ORDER BY '+LTRIM(@FieldOrder)
    IF ISNULL(@Where,N'')=N''
    SET @Where=N''
    ELSE
    SET @Where=N'WHERE ('+@Where+N')'--如果@PageCount为NULL值,则计算总页数(这样设计可以只在第一次计算总页数,以后调用时,把总页数传回给存储过程,避免再次计算总页数,对于不想计算总页数的处理而言,可以给@PageCount赋值)
    IF @PageCount IS NULL
    BEGIN
    DECLARE @sql nvarchar(4000)
    SET @sql=N'SELECT @PageCount=COUNT(*)'
    +N' FROM '+@tbname
    +N' '+@Where
    EXEC sp_executesql @sql,N'@PageCount int OUTPUT',@PageCount OUTPUT
    SET @PageCount=(@PageCount+@PageSize-1)/@PageSize
    END--计算分页显示的TOPN值
    DECLARE @TopN varchar(20),@TopN1 varchar(20)
    SELECT @TopN=@PageSize,
    @TopN1=(@PageCurrent-1)*@PageSize--第一页直接显示
    IF @PageCurrent=1
    EXEC(N'SELECT TOP '+@TopN
    +N' '+@FieldShow
    +N' FROM '+@tbname
    +N' '+@Where
    +N' '+@FieldOrder)
    ELSE
    BEGIN
    --处理别名
    IF @FieldShow=N'*'
    SET @FieldShow=N'a.*' --生成主键(惟一键)处理条件
    DECLARE @Where1 nvarchar(4000),@Where2 nvarchar(4000),
    @s nvarchar(1000),@Field sysname
    SELECT @Where1=N'',@Where2=N'',@s=@FieldKey
    WHILE CHARINDEX(N',',@s)>0
    SELECT @Field=LEFT(@s,CHARINDEX(N',',@s)-1),
    @s=STUFF(@s,1,CHARINDEX(N',',@s),N''),
    @Where1=@Where1+N' AND a.'+@Field+N'=b.'+@Field,
    @Where2=@Where2+N' AND b.'+@Field+N' IS NULL',
    @Where=REPLACE(@Where,@Field,N'a.'+@Field),
    @FieldOrder=REPLACE(@FieldOrder,@Field,N'a.'+@Field),
    @FieldShow=REPLACE(@FieldShow,@Field,N'a.'+@Field)
    SELECT @Where=REPLACE(@Where,@s,N'a.'+@s),
    @FieldOrder=REPLACE(@FieldOrder,@s,N'a.'+@s),
    @FieldShow=REPLACE(@FieldShow,@s,N'a.'+@s),
    @Where1=STUFF(@Where1+N' AND a.'+@s+N'=b.'+@s,1,5,N''),
    @Where2=CASE
    WHEN @Where='' THEN N'WHERE ('
    ELSE @Where+N' AND ('
    END+N'b.'+@s+N' IS NULL'+@Where2+N')' --执行查询
    EXEC(N'SELECT TOP '+@TopN
    +N' '+@FieldShow
    +N' FROM '+@tbname
    +N' a LEFT JOIN(SELECT TOP '+@TopN1
    +N' '+@FieldKey
    +N' FROM '+@tbname
    +N' a '+@Where
    +N' '+@FieldOrder
    +N')b ON '+@Where1
    +N' '+@Where2
    +N' '+@FieldOrder)
    END-- 字符串缓存实现的通用分页存储过程(转自邹建)
    CREATE PROC sp_PageView
    @tbname     sysname,            --要分页显示的表名
    @FieldKey   sysname,            --用于定位记录的主键(惟一键)字段,只能是单个字段
    @PageCurrent int=1,              --要显示的页码
    @PageSize   int=10,             --每页的大小(记录数)
    @FieldShow  nvarchar(1000)='',   --以逗号分隔的要显示的字段列表,如果不指定,则显示所有字段
    @FieldOrder  nvarchar(1000)='',  --以逗号分隔的排序字段列表,可以指定在字段后面指定DESC/ASC
                                              用于指定排序顺序
    @Where     nvarchar(1000)='',   --查询条件
    @PageCount  int OUTPUT         --总页数
    AS
    DECLARE @sql nvarchar(4000)
    SET NOCOUNT ON
    --检查对象是否有效
    IF OBJECT_ID(@tbname) IS NULL
    BEGIN
    RAISERROR(N'对象"%s"不存在',1,16,@tbname)
    RETURN
    END
    IF OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTable')=0
    AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsView')=0
    AND OBJECTPROPERTY(OBJECT_ID(@tbname),N'IsTableFunction')=0
    BEGIN
    RAISERROR(N'"%s"不是表、视图或者表值函数',1,16,@tbname)
    RETURN
    END--分页字段检查
    IF ISNULL(@FieldKey,N'')=''
    BEGIN
    RAISERROR(N'分页处理需要主键(或者惟一键)',1,16)
    RETURN
    END--其他参数检查及规范
    IF ISNULL(@PageCurrent,0)<1 SET @PageCurrent=1
    IF ISNULL(@PageSize,0)<1 SET @PageSize=10
    IF ISNULL(@FieldShow,N'')=N'' SET @FieldShow=N'*'
    IF ISNULL(@FieldOrder,N'')=N''
    SET @FieldOrder=N''
    ELSE
    SET @FieldOrder=N'ORDER BY '+LTRIM(@FieldOrder)
    IF ISNULL(@Where,N'')=N''
    SET @Where=N''
    ELSE
    SET @Where=N'WHERE ('+@Where+N')'--如果@PageCount为NULL值,则计算总页数(这样设计可以只在第一次计算总页数,以后调用时,把总页数传回给存储过程,避免再次计算总页数,对于不想计算总页数的处理而言,可以给@PageCount赋值)
    IF @PageCount IS NULL
    BEGIN
    SET @sql=N'SELECT @PageCount=COUNT(*)'
    +N' FROM '+@tbname
    +N' '+@Where
    EXEC sp_executesql @sql,N'@PageCount int OUTPUT',@PageCount OUTPUT
    SET @PageCount=(@PageCount+@PageSize-1)/@PageSize
    END--计算分页显示的TOPN值
    DECLARE @TopN varchar(20),@TopN1 varchar(20)
    SELECT @TopN=@PageSize,
    @TopN1=@PageCurrent*@PageSize --第一页直接显示
    IF @PageCurrent=1
    EXEC(N'SELECT TOP '+@TopN
    +N' '+@FieldShow
    +N' FROM '+@tbname
    +N' '+@Where
    +N' '+@FieldOrder)
    ELSE
    BEGIN
    SELECT @PageCurrent=@TopN1,
    @sql=N'SELECT @n=@n-1,@s=CASE WHEN @n<'+@TopN
    +N' THEN @s+N'',''+QUOTENAME(RTRIM(CAST('+@FieldKey
    +N' as varchar(8000))),N'''''''') ELSE N'''' END FROM '+@tbname
    +N' '+@Where
    +N' '+@FieldOrder
    SET ROWCOUNT @PageCurrent
    EXEC sp_executesql @sql,
    N'@n int,@s nvarchar(4000) OUTPUT',
    @PageCurrent,@sql OUTPUT
    SET ROWCOUNT 0
    IF @sql=N''
    EXEC(N'SELECT TOP 0'
    +N' '+@FieldShow
    +N' FROM '+@tbname)
    ELSE
    BEGIN
    SET @sql=STUFF(@sql,1,1,N'')
    --执行查询
    EXEC(N'SELECT TOP '+@TopN
    +N' '+@FieldShow
    +N' FROM '+@tbname
    +N' WHERE '+@FieldKey
    +N' IN('+@sql
    +N') '+@FieldOrder)
    END
    END
      

  3.   

    谢谢!!!不过公司非让用JSP+Servlet的开发模式,我也没办法,我想用SSH的架构,结果老板直接驳回了,哎...