zoukankan      html  css  js  c++  java
  • 千万级分页高效存储过程

    这两天测试了前几天写的SQL2005专用分页的存储过程,当数据量达到2千多万的时候,效率相当的低,每次执行都要8秒左右(CPU:Q6600)。不过在2百多万数据量的情况下性能还是蛮不错的,在网上找了找,发现这下面的这两个,其实还是一个,不过后面那个是灵活了许多,仅供参考。
    复制  保存
    /******
    Object:  StoredProcedure [dbo].[GetRecordFromPage]
    Script Date: 07/23/2008 18:42:05
    ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    /*
    函数名称: GetRecordFromPage
    函数功能: 获取指定页的数据
    参数说明: @tblName      包含数据的表名
    @fldName      关键字段名
    @PageSize     每页记录数
    @PageIndex    要获取的页码
    @OrderType    排序类型, 0 - 升序, 1 - 降序
    @strWhere     查询条件 (注意: 不要加 where)
    */
    ALTER PROCEDURE [dbo].[GetRecordFromPage]
    @tblName      varchar(255),       -- 表名
        @fldName      varchar(255),       -- 字段名
        @PageSize     int = 10,           -- 页尺寸
        @PageIndex    int = 1,            -- 页码
        @OrderType    bit = 0,            -- 设置排序类型, 非 0 值则降序
        @strWhere     varchar(2000) = ''  -- 查询条件 (注意: 不要加 where)
    AS
    declare @strSQL   varchar(6000)       -- 主语句
    declare @strTmp   varchar(1000)       -- 临时变量
    declare @strOrder varchar(500)        -- 排序类型
    
    if @OrderType != 0
    begin
    set @strTmp = '<(select min'
    set @strOrder = ' order by [' + @fldName +'] desc'
    end
    else
    begin
    set @strTmp = '>(select max'
    set @strOrder = ' order by [' + @fldName +'] asc'
    end
    set @strSQL = 'select top ' + str(@PageSize) + ' * 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) + ' * from ['
    + @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
    + @fldName + ']) from (select top ' + str((@PageIndex-1)*@PageSize) + ' ['
    + @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '
    + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
    if @PageIndex = 1
    begin
    set @strTmp = ''
    if @strWhere != ''
    set @strTmp = ' where (' + @strWhere + ')'
    set @strSQL = 'select top ' + str(@PageSize) + ' * from ['
    + @tblName + ']' + @strTmp + ' ' + @strOrder
    end
    exec (@strSQL)

    这是我目前见过效率最高的,不过它的order by 是不是有点儿问题,不能指定某一个,还有没有返回总记录数。于是有了下面这个改进的。

    如果需要总页数还可以再改一下,不过目前已经足够用了,当然,当达到千万数据量后,比上面的效率上稍微低了一点点,不过还不算太坏,

    比较推荐下面这个。
    复制  保存
    /******
    Object:  StoredProcedure [dbo].[usp_GetRecordFromPage]
    Script Date: 07/23/2008 18:42:37
    ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE       PROCEDURE [dbo].[usp_GetRecordFromPage]
    @tblName       varchar(1000),        -- 表名
        @SelectFieldName    varchar(4000),              -- 要显示的字段名(不要加select)
        @strWhere       varchar(4000),              -- 查询条件(注意: 不要加 where)
        @OrderFieldName      varchar(255),               -- 排序索引字段名
        @PageSize       int ,                 -- 页大小
        @PageIndex      int = 1,                  -- 页码
        @iRowCount      int output,                 -- 返回记录总数
        @OrderType      bit = 0                  -- 设置排序类型, 非 0 值则降序
    
    AS
    declare @strSQL    varchar(4000)       -- 主语句
    declare @strTmp    varchar(4000)        -- 临时变量
    declare @strOrder  varchar(400)        -- 排序类型
    declare @strRowCount    nvarchar(4000)      -- 用于查询记录总数的语句
    
    set @OrderFieldName=ltrim(rtrim(@OrderFieldName))
    if @OrderType != 0
    begin
    set @strTmp = '<(select min'
    set @strOrder = ' order by ' + @OrderFieldName +' desc'
    end
    else
    begin
    set @strTmp = '>(select max'
    set @strOrder = ' order by ' + @OrderFieldName +' asc'
    end
    set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from '
    + @tblName + ' where ' + @OrderFieldName + @strTmp + '('
    + right(@OrderFieldName,len(@OrderFieldName)-charindex('.',@OrderFieldName)) + ') from (select top ' + str((@PageIndex-1)*@PageSize)
    + @OrderFieldName + ' from ' + @tblName  + @strOrder + ') as tblTmp)'
    + @strOrder
    if @strWhere != ''
    set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from '
    + @tblName + ' where ' + @OrderFieldName + @strTmp + '('
    + right(@OrderFieldName,len(@OrderFieldName)-charindex('.',@OrderFieldName)) + ') from (select top ' + str((@PageIndex-1)*@PageSize)
    + @OrderFieldName + ' from ' + @tblName + ' where ' + @strWhere + ' '
    + @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
    if @PageIndex = 1
    begin
    set @strTmp = ''
    if @strWhere != ''
    set @strTmp = ' where ' + @strWhere
    set @strSQL = 'select top ' + str(@PageSize) + @SelectFieldName+' from '
    + @tblName + @strTmp + ' ' + @strOrder
    end
    exec(@strSQL)
    if @strWhere!=''
    begin
    set @strRowCount = 'select @iRowCount=count(*) from ' + @tblName+' where '+@strWhere
    end
    else
    begin
    set @strRowCount = 'select @iRowCount=count(*) from ' + @tblName
    end
    exec sp_executesql @strRowCount,N'@iRowCount int out',@iRowCount out
  • 相关阅读:
    Time Zone 【模拟时区转换】(HDU暑假2018多校第一场)
    HDU 1281 棋盘游戏 【二分图最大匹配】
    Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
    Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) 【思维】
    Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】
    Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】
    Avito Cool Challenge 2018 E. Missing Numbers 【枚举】
    Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】
    005 如何分析问题框架
    004 如何定义和澄清问题
  • 原文地址:https://www.cnblogs.com/lzhdim/p/1368817.html
Copyright © 2011-2022 走看看