数据库的查询优化及分页算法方案

上传人:飞*** 文档编号:5454776 上传时间:2017-08-30 格式:DOC 页数:45 大小:69KB
返回 下载 相关 举报
数据库的查询优化及分页算法方案_第1页
第1页 / 共45页
数据库的查询优化及分页算法方案_第2页
第2页 / 共45页
数据库的查询优化及分页算法方案_第3页
第3页 / 共45页
数据库的查询优化及分页算法方案_第4页
第4页 / 共45页
数据库的查询优化及分页算法方案_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《数据库的查询优化及分页算法方案》由会员分享,可在线阅读,更多相关《数据库的查询优化及分页算法方案(45页珍藏版)》请在金锄头文库上搜索。

1、海量数据库的 查询优化及分页算法方案字体大小: 小 中 大 随着“金盾工程”建设的逐步深入和公安信息化的高速发展,公安计算机应用系统被广泛应用在各警种、各部门。与此同时,应用系统体系的核心、系统数据的存放地数据库也随着实际应用而急剧膨胀,一些大规模的系统,如人口系统的数据甚至超过了 1000 万条,可谓海量。那么,如何实现快速地从这些超大容量的数据库中提取数据(查询)、分析、统计以及提取数据后进行数据分页已成为各地系统管理员和数据库管理员亟待解决的难题。在以下的文章中,我将以“办公自动化” 系统为例,探讨如何在有着 1000 万条数据的 MS SQL SERVER 数据库中实现快速的数据提取和

2、数据分页。以下代码说明了我们实例中数据库的“红头文件” 一表的部分数据结构:CREATE TABLE dbo.TGongwen ( -TGongwen 是红头文件表名Gid int IDENTITY (1, 1) NOT NULL ,-本表的 id 号,也是主键title varchar (80) COLLATE Chinese_PRC_CI_AS NULL ,-红头文件的标题fariqi datetime NULL ,-发布日期neibuYonghu varchar (70) COLLATE Chinese_PRC_CI_AS NULL ,-发布用户reader varchar (900)

3、COLLATE Chinese_PRC_CI_AS NULL ,-需要浏览的用户。每个用户中间用分隔符“,”分开) ON PRIMARY TEXTIMAGE_ON PRIMARYGO下面,我们来往数据库中添加 1000 万条数据:declare i intset i=1while i dateadd(day,-90,getdate()用时:53763 毫秒(54 秒)(3)将聚合索引建立在日期列(fariqi)上:select gid,fariqi,neibuyonghu,title from Tgongwenwhere fariqi dateadd(day,-90,getdate()用时:2

4、423 毫秒(2 秒)虽然每条语句提取出来的都是 25 万条数据,各种情况的差异却是巨大的,特别是将聚集索引建立在日期列时的差异。事实上,如果您的数据库真的有 1000万容量的话,把主键建立在 ID 列上,就像以上的第 1、2 种情况,在网页上的表现就是超时,根本就无法显示。这也是我摒弃 ID 列作为聚集索引的一个最重要的因素。得出以上速度的方法是:在各个 select 语句前加:declare d datetimeset d=getdate()并在 select 语句后加:select 语句执行花费时间(毫秒)=datediff(ms,d,getdate()2、只要建立索引就能显著提高查询速

5、度事实上,我们可以发现上面的例子中,第 2、3 条语句完全相同,且建立索引的字段也相同;不同的仅是前者在 fariqi 字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。从建表的语句中,我们可以看到这个有着 1000 万数据的表中 fariqi 字段有5003 个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中,我们每天都会发几个文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同” 的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查

6、询速度是非常重要的。3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度上面已经谈到:在进行数据查询时都离不开字段的是“日期” 还有用户本身的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合并起来,建立一个复合索引(compound index)。很多人认为只要把任何字段加进聚集索引,就能提高查询速度,也有人感到迷惑:如果把复合的聚集索引字段分开查询,那么查询速度会减慢吗?带着这个问题,我们来看一下以下的查询速度(结果集都是 25 万条数据):(日期列fariqi 首先排在复合聚集索引的起始列,用户名 neibuyonghu 排在后列)(1)select gid,fariq

7、i,neibuyonghu,title from Tgongwen where fariqi2004-5-5查询速度:2513 毫秒(2)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi2004-5-5 and neibuyonghu=办公室 查询速度:2516 毫秒(3)select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu=办公室查询速度:60280 毫秒从以上试验中,我们可以看到如果仅用聚集索引的起始列作为查询条件和同时用到复合聚集索

8、引的全部列的查询速度是几乎一样的,甚至比用上全部的复合索引列还要略快(在查询结果集数目一样的情况下);而如果仅用复合聚集索引的非起始列作为查询条件的话,这个索引是不起任何作用的。当然,语句1、2 的查询速度一样是因为查询的条目数一样,如果复合索引的所有列都用上,而且查询结果少的话,这样就会形成“索引覆盖” ,因而性能可以达到最优。同时,请记住:无论您是否经常使用聚合索引的其他列,但其前导列一定要是使用最频繁的列。(四)其他书上没有的索引使用经验总结1、用聚合索引比用不是聚合索引的主键速度快下面是实例语句:(都是提取 25 万条数据)select gid,fariqi,neibuyonghu,r

9、eader,title from Tgongwen where fariqi=2004-9-16使用时间:3326 毫秒select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid2004-1-1用时:6343 毫秒(提取 100 万条)select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi2004-6-6用时:3170 毫秒(提取 50 万条)select gid,fariqi,neibuyonghu,reader,title from

10、Tgongwen where fariqi=2004-9-16用时:3326 毫秒(和上句的结果一模一样。如果采集的数量一样,那么用大于号和等于号是一样的)select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi2004-1-1 and fariqi2004-1-1 order by fariqi用时:6390 毫秒select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi 10000和执行:select * from table1

11、where tID 10000 and name=zhangsan一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果 tID 是一个聚合索引,那么后一句仅仅从表的 10000 条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个 name=zhangsan的,而后再根据限制条件条件 tID10000 来提出查询结果。事实上,这样的担心是不必要的。SQL SERVER 中有一个“ 查询分析优化器”,它可以计算出 where 子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。虽然查询优化器可以根据 wher

12、e 子句自动的进行查询优化,但大家仍然有必要了解一下“查询优化器”的工作原理,如非这样,有时查询优化器就会不按照您的本意进行快速查询。在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。SARG 的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值得范围内的匹配或者两个以上条件的 AND 连接。形式如下:列名 操作符 或操作符列名列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如:Name=张三价格500050005000如果一个表达

13、式不能满足 SARG 的形式,那它就无法限制搜索的范围了,也就是 SQL SERVER 必须对每一行都判断它是否满足 WHERE 子句中的所有条件。所以一个索引对于不满足 SARG 形式的表达式来说是无用的。介绍完 SARG 后,我们来总结一下使用 SARG 以及在实践中遇到的和某些资料上结论不同的经验:1、Like 语句是否属于 SARG 取决于所使用的通配符的类型如:name like 张% ,这就属于 SARG而:name like %张 , 就不属于 SARG。原因是通配符%在字符串的开通使得索引无法使用。2、or 会引起全表扫描Name=张三 and 价格5000 符号 SARG,而

14、:Name= 张三 or 价格5000 则不符合 SARG。使用 or 会引起全表扫描。3、非操作符、函数引起的不满足 SARG 形式的语句不满足 SARG 形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、NOT EXISTS、NOT IN、NOT LIKE 等,另外还有函数。下面就是几个不满足 SARG 形式的例子:ABS(价格)5000SQL SERVER 也会认为是 SARG,SQL SERVER 会将此式转化为:WHERE 价格2500/2但我们不推荐这样使用,因为有时 SQL SERVER 不能保证这种转化与原始表达式是完全等价的。4、IN 的作用相当与 OR语句:S

15、elect * from table1 where tid in (2,3)和Select * from table1 where tid=2 or tid=3是一样的,都会引起全表扫描,如果 tid 上有索引,其索引也会失效。5、尽量少用 NOT6、exists 和 in 的执行效率是一样的很多资料上都显示说,exists 要比 in 的执行效率要高,同时应尽可能的用 not exists 来代替 not in。但事实上,我试验了一下,发现二者无论是前面带不带not,二者之间的执行效率都是一样的。因为涉及子查询,我们试验这次用 SQL SERVER 自带的 pubs 数据库。运行前我们可以把

16、 SQL SERVER 的 statistics I/O状态打开。(1)select title,price from titles where title_id in (select title_id from sales where qty30)该句的执行结果为:表 sales。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。表 titles。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。(2)select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty30)第二句的执行结果为:表 sales。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 企业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号