• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >数据库其它 > 海量数据库的查询优化及分页算法方案集合2/2

海量数据库的查询优化及分页算法方案集合2/2

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-11

通过本文主要向大家介绍了海量数据库解决方案,海量数据库,数据库 海量数据,海量数据处理算法,海量阅读实施方案等相关知识,希望本文的分享对您有所帮助
FROM publish 
WHERE (id NOT IN 
    (SELECT TOP n-1 id 
     FROM publish)) 
id 为publish 表的关键字 
我当时看到这篇文章的时候,真的是精神为之一振,觉得思路非常得好。等到后来,我在作办公自动化系统(ASP.NET+ C#+SQL SERVER)的时候,忽然想起了这篇文章,我想如果把这个语句改造一下,这就可能是一个非常好的分页存储过程。于是我就满网上找这篇文章,没想到,文章还没找到,却找到了一篇根据此语句写的一个分页存储过程,这个存储过程也是目前较为流行的一种分页存储过程,我很后悔没有争先把这段文字改造成存储过程:
CREATE PROCEDURE pagination2
(
 @SQL nVARCHAR(4000),    --不带排序语句的SQL语句
 @Page int,              --页码
 @RecsPerPage int,       --每页容纳的记录数
 @ID VARCHAR(255),       --需要排序的不重复的ID号
 @Sort VARCHAR(255)      --排序字段及规则
)
AS
DECLARE @Str nVARCHAR(4000)
SET @Str='SELECT   TOP '+CAST(@RecsPerPage AS VARCHAR(20))+' * FROM ('+@SQL+') T WHERE T.'+@ID+'NOT IN 
(SELECT   TOP '+CAST((@RecsPerPage*(@Page-1)) AS VARCHAR(20))+' '+@ID+' FROM ('+@SQL+') T9 ORDER BY '+@Sort+') ORDER BY '+@Sort
PRINT @Str
EXEC sp_ExecuteSql @Str
GO
其实,以上语句可以简化为:
SELECT TOP 页大小 *
FROM Table1
WHERE (ID NOT IN
          (SELECT TOP 页大小*页数 id
         FROM 表
         ORDER BY id))
ORDER BY ID
但这个存储过程有一个致命的缺点,就是它含有NOT IN字样。虽然我可以把它改造为:
SELECT TOP 页大小 *
FROM Table1
WHERE not exists
(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )
order by id
即,用not exists来代替not in,但我们前面已经谈过了,二者的执行效率实际上是没有区别的。
既便如此,用TOP 结合NOT IN的这个方法还是比用游标要来得快一些。
虽然用not exists并不能挽救上个存储过程的效率,但使用SQL SERVER中的TOP关键字却是一个非常明智的选择。因为分页优化的最终目的就是避免产生过大的记录集,而我们在前面也已经提到了TOP的优势,通过TOP 即可实现对数据量的控制。
在分页算法中,影响我们查询速度的关键因素有两点:TOP和NOT IN。TOP可以提高我们的查询速度,而NOT IN会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN,同其他方法来替代它。
我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min作为分水岭,使其成为分页算法中分开每页的参照物。在这里,我们可以用操作符“>”或“<”号来完成这个使命,使查询语句符合SARG形式。如:
Select top 10 * from table1 where id>200
于是就有了如下分页方案:
select top 页大小 *
from table1 
where id>
      (select max (id) from 
      (select top ((页码-1)*页大小) id from table1 order by id) as T
       )     
  order by id
在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。下表列出了笔者用有着1000万数据的办公自动化系统中的表,在以GID(GID是主键,但并不是聚集索引。)为排序列、提取gid,fariqi,title字段,分别以第1、10、100、500、1000、1万、10万、25万、50万页为例,测试以上三种分页方案的执行速度:(单位:毫秒)
页  码
 方案1
 方案2
 方案3
1
 60
 30
 76
10
 46
 16
 63
100
 1076
 720
 130
500
 540
 12943
 83
1000
 17110
 470
 250
1万
 24796
 4500
 140
10万
 38326
 42283
 1553
25万
 28140
 128720
 2330
50万
 121686
 127846
 7168
从上表中,我们可以看出,三种存储过程在执行100页以下的分页命令时,都是可以信任的,速度都很好。但第一种方案在执行分页1000页以上后,速度就降了下来。第二种方案大约是在执行分页1万页以上后速度开始降了下来。而第三种方案却始终没有大的降势,后劲仍然很足。
在确定了第三种分页方案后,我们可以据此写一个存储过程。大家知道SQL SERVER的存储过程是事先编译好的SQL语句,它的执行效率要比通过WEB页面传来的SQL语句的执行效率要高。下面的存储过程不仅含有分页方案,还会根据页面传来的参数来确定是否进行数据总数统计。
-- 获取指定页的数据
CREATE PROCEDURE pagination3
@tblName   varchar(255),       -- 表名
@strGetFields varchar(1000) = '*',  -- 需要返回的列 
@fldName varchar(255)='',      -- 排序的字段名
@PageSize   int = 10,          -- 页尺寸
@PageIndex  int = 1,           -- 页码
@doCount  bit = 0,   -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0,  -- 设置排序类型, 非 0 值则降序
@strWhere  varchar(1500) = ''  -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL   varchar(5000)       -- 主语句
declare @strTmp   varchar(110)        -- 临时变量
declare @strOrder varchar(400)        -- 排序类型
if @doCount != 0
  begin
    if @strWhere !=''
    set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere
    else
    set @strSQL = "select count(*) as Total from [" + @tblName + "]"
end  
--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
else
begin
if @OrderType != 0
begin
    set @strTmp = "<(select min"
set @strOrder = " order by [" + @fldName +"] desc"
--如果@OrderType不是0,就执行降序,这句很重要!
end
else
begin
    set @strTmp = ">(select max"
    set @strOrder = " order by [" + @fldName +"] asc"
end
if @PageIndex = 1
begin
    if @strWhere != ''   
    set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "  from [" + @tblName
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 当数据库变慢时的解决方法
  • 海量数据库的查询优化及分页算法方案集合2/2
  • 海量数据库的查询优化及分页算法方案集合1/2第1/2页
  • 海量数据库的查询优化及分页算法方案 2 之 改良SQL语句

相关文章

  • 2017-05-11在ACCESS和SQL Server下Like 日期类型查询区别
  • 2017-05-11mysql "group by"与"order by"的研究--分类中最新的内容
  • 2017-05-11多种获取远程连接access数据库的方法
  • 2017-05-11带参数的sql和不带参数的sql存储过程区别第1/2页
  • 2017-05-11SQL 优化经验总结34条
  • 2017-05-11举例简单介绍PostgreSQL中的数组
  • 2017-05-11SQL select distinct的使用方法
  • 2017-05-11多条件查询的程序
  • 2017-05-11修改插入时间不匹配问题
  • 2017-05-11SQL之left join、right join、inner join的区别浅析

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • 本地SQL注射攻略分析曝光
    • sqlserver、Mysql、Oracle三种数据库的优缺点总结
    • 深入SQL中PIVOT 行列转换详解
    • WordPress导入数据库出现”Unknown collation: ‘utf8mb4_unicode_ci”错误的解决办法
    • mssql注入躲避IDS的方法
    • 使用.pgpass密码文件,通过psql登录greenplum
    • 三表左连接查询的sql语句写法
    • MySQL mysqldump命令使用详解
    • 最新统计排名前十的SQL和NoSQL数据库排行榜
    • 数据库基本概念面试必问

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有