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
  • 相关阅读:
    el-input 标签中密码的显示和隐藏
    java 使用RedisTemplate实现Redis事务
    mac 安装 Java 环境
    Snowflake 分布式UUID
    lsof 查看端口使用时刻
    nginx.pid" failed (2: No such file or directory)
    解决Redis之MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist
    Linux环境下 Jna 解决so依赖文件not found
    Ubuntu mysql 在线安装
    Linux中为什么执行自己的程序要在前面加./
  • 原文地址:https://www.cnblogs.com/lzhdim/p/1368817.html
Copyright © 2011-2022 走看看