设为首页 加入收藏

TOP

SQL优化-索引、查询优化及分页算法方案(五)
2014-11-24 02:57:15 来源: 作者: 【 】 浏览:20
Tags:SQL 优化 索引 查询 算法 方案
eibuyonghu,reader,title from Tgongwen
  where fariqi='2004-9-16' or fariqi='2004-2-5'
  用时:6423毫秒。扫描计数 2,逻辑读 14726 次,物理读 1 次,预读 7176 次。
  select gid,fariqi,neibuyonghu,reader,title from Tgongwen
  where fariqi='2004-9-16'
  union
  select gid,fariqi,neibuyonghu,reader,title from Tgongwen
  where fariqi='2004-2-5'
  用时:11640毫秒。扫描计数 8,逻辑读 14806 次,物理读 108 次,预读 1144 次。

  9、字段提取要按照“需多少、提多少”的原则,避免“select *”

  我们来做一个试验:
  select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
  用时:4673毫秒
  select top 10000 gid,fariqi,title from tgongwen order by gid desc
  用时:1376毫秒
  select top 10000 gid,fariqi from tgongwen order by gid desc
  用时:80毫秒
  由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。

  10、count(*)不比count(字段)慢

  某些资料上说:用*会统计所有列,显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看:
  select count(*) from Tgongwen
  用时:1500毫秒
  select count(gid) from Tgongwen
  用时:1483毫秒
  select count(fariqi) from Tgongwen
  用时:3140毫秒
  select count(title) from Tgongwen
  用时:52050毫秒

  从以上可以看出,如果用count(*)和用count(主键)的速度是相当的,而count(*)却比其他任何除主键以外的字段汇总速度要快,而且字段越长,汇总的速度就越慢。我想,如果用count(*), SQL SERVER可能会自动查找最小字段来汇总的。当然,如果您直接写count(主键)将会来的更直接些。

  11、order by按聚集索引列排序效率最高

  我们来看:(gid是主键,fariqi是聚合索引列)
  select top 10000 gid,fariqi,reader,title from tgongwen
  用时:196 毫秒。 扫描计数 1,逻辑读 289 次,物理读 1 次,预读 1527 次。
  select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc
  用时:4720毫秒。 扫描计数 1,逻辑读 41956 次,物理读 0 次,预读 1287 次。
  select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
  用时:4736毫秒。 扫描计数 1,逻辑读 55350 次,物理读 10 次,预读 775 次。
  select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc
  用时:173毫秒。 扫描计数 1,逻辑读 290 次,物理读 0 次,预读 0 次。
  select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc
  用时:156毫秒。 扫描计数 1,逻辑读 289 次,物理读 0 次,预读 0 次。
  从以上我们可以看出,不排序的速度以及逻辑读次数都是和“order by 聚集索引列” 的速度是相当的,但这些都比“order by 非聚集索引列”的查询速度是快得多的。
  同时,按照某个字段进行排序的时候,无论是正序还是倒序,速度是基本相当的。

  12、高效的TOP

  事实上,在查询和提取超大容量的数据集时,影响数据库响应时间的最大因素不是数据查找,而是物理的I/0操作。如:
  select top 10 * from (
  select top 10000 gid,fariqi,title from tgongwen
  where neibuyonghu='办公室'order by gid desc) as a
  order by gid asc
  这条语句,从理论上讲,整条语句的执行时间应该比子句的执行时间长,但事实相反。因为,子句执行后返回的是10000条记录,而整条语句仅返回10条语句,所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP确实很好用,效率也很高。但这个词在另外一个大型数据库ORACLE中却没有,这不能说不是一个遗憾,虽然在ORACLE中可以用其他方法(如:rownumber)来解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP这个关键词。
  到此为止,我们上面讨论了如何实现从大容量的数据库中快速地查询出您所需要的数据方法。当然,我们介绍的这些方法都是“软”方法,在实践中,我们还要考虑各种“硬”因素,如:网络性能、服务器的性能、操作系统的性能,甚至网卡、交换机等。

  三、实现小数据量和海量数据的通用分页显示存储过程

  建立一个web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。

  更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。

  最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。

  后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程: 
 
CREATE procedure pagination1
  (@pagesize int, --页面大小,如每页存储20条记录
  @pageindex int --当前页码
  )
  as
  set nocount on //不返回计数,不返回任何结果集
  begin
  declare @indextable table(id int identity(1,1),nid int) --定义表变量
  declare @PageLowerBound int --定义此页的底码
  declare @PageUpperBound int --定义此页的顶码
  set @PageLow

首页 上一页 2 3 4 5 6 7 下一页 尾页 5/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇PL/SQL编程 下一篇T-SQL问题解决集锦――数据加解密

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C语言结构体怎么直接 (2025-12-24 17:19:44)
·为什么指针作为c语言 (2025-12-24 17:19:41)
·如何较为深入的理解c (2025-12-24 17:19:38)
·Announcing October (2025-12-24 15:18:16)
·MySQL有什么推荐的学 (2025-12-24 15:18:13)