SQL Server与Oracle数据库在查询优化上的差异
一、 在数据库排序查询优化上的差异。
在讲解这个内容之前,为了读者能够清楚我讲的内容,我要先谈一个概念。命中率,它是指从内存中取得数据而不从磁盘中取得数据的比率。我们在前几篇文章中都提到过,当在数据库中查询数据时,数据库服务器都是先从内存中寻找数据。只有在内存中数据不存在的情况下,才会去读取数据库文件的内容。而且,从内存中查询数据要比在数据库文件中查询数据效率高得多。从这方面讲,我们若能够提高这个查询的命中率,则显然可以提高数据库系统的查询效率。
虽然SQL Server与Oracle在这方面都有所作为,但是,笔者认为,Oracle数据库在这方面的优势比较明显。特别是Oracle数据库采用了临时段的管理机制,明显提高了数据库查询的命中率。
那什么叫作数据库的临时段呢?假设当我们刚查完员工信息表后,此时,员工信息表的内容就存在数据库服务器的内存中。此时,我们需要对这个表进行排序查询,如我们希望查询出工龄超过两年的员工,并且按工龄的长短进行排序。此时,Oracle数据库服务器会设法在内存中排序区对所有行进行排序。而这个排序区的大小则有数据库的初始化文件init.ora进行确定。当这个排序区不够大,不能够容纳我们所查询出来的员工信息记录数时,数据库就会在排序操作期间,在数据库服务器中开辟临时段。很明显,在查询操作过程中,若开辟临时段的话,会减低数据库的命中率,降低排序查询的效率。我们现在希望这个排序能够在内存中完成,而不需要开辟额外的临时段,如此的话,就可以消除向临时段写数据的开销,提高排序查询的效率。所以,当我们数据库中的数据比较庞大时,我们可以考虑增加这个排序区的长度,以避免临时段的需要。正是这个临时段的问题,如我们刚查询完员工信息表,查询完成之后,再对该表进行排序查询,就觉得好像仍然是新的查询一样。其实,这个排序查询的问题,我们可以通过一定的方法对此进行优化,以提高排序查询的效率。
修改方法:
第一步:先利用查询语句判断,是否有临时段需求的产生。
select * from v$sysstat where name='dtmfg(disk)' or name='dtmfg(memory)';
如我们可以定时利用以上语句,来查询是否有临时段需求的产生。这条语句中,dtmfg是具体的数据库实例名,我们只需要修改这个名字,就可以查询到我们需要的内容。若在查询结果中,发现有临时段需求产生的话,则就需要考虑修改相关的配置文件,以优化排序查询性能。
第二步:修改参数配置文件。
我们需要修改inint.ora文件,修改里面的SORT-AREA-SIZE的值。不过,修改这个配置文件之后,还必须重新启动数据库才会生效。一般情况下,数据库管理员需要定时查询这个临时段需求,然后根据情况,不断的进行调整,做好数据排序查询优化功能。
而在微软的SQL Server数据库中,笔者没有发现类似的功能。
二、 利用哈希联接,提高多表查询性能。
多表之间的关联查询,无论是哪种关联类型,到数据量比较大时,对于数据库服务器的查询性能都是一个非常大的考验。所以,在实际数据库设计中,当数据量比较大的时候,需要采用哈希联接,来提高数据库多表查询的效率。一般来说,哈希联接比其他几种表之间的连接方式,对于服务器来说开销要小得多,从而可以提高服务器的查询效率。
哈希联接一共有三种联接方式,分别为内存中的哈希联结、Gracle哈希联接与递归哈希联接。
所谓内存的哈希联接,是指先扫描或计算整个生成输入,然后在内存中生成哈希表。根据哈希键计算出哈希值,然后将每行插入哈希存储。如果整个生成输入比可用内存少,则可以将所有行都插入到哈希表中。生成阶段之后就是探测阶段。一次一行的3对整个探测输入进行扫描或者计算,并为每个探测行计算哈希健的值,并按一定的规则生成匹配项。
其他两种哈希联接也各有各的用途,在这里就不重复描述了。下面,笔者谈谈在这两个数据库中,对于哈希联接所持的不同态度。
在微软的SQL Server数据库中,默认情况下,是采用哈希联接的。在优化过程中并不能够确定到底采用上面的那种联接方式。所以,微软的数据库系统默认情况下,实采用内存中的哈希联接,然后再根据生成输入的大小逐渐转换到GRACLE哈希联接以及递归哈希联接。
但是,若是在数据量不大的情况下,哈希联接不但不会提高数据库的查询效率,反而会有所下降。所以,Oracle数据库在默认情况下,是没有启用哈希联接的,而是在实际需要时,可添加一些设置使得数据库在有多大联接查询发生时才利用哈希联结。也就是说,Oracle数据库可以设置判断条件,数据库管理员可以指定,当满足一定的条件时才调用哈希联结,利用它来提高多表查询的效率。
三、 大表查询优化。
一般来说,在数据库设计中,数据库设计人员会利用索引等技术来提高数据库的查询效率。但是,索引的作用,也不是无限扩大的,它受到一定的限制。一般来说,他跟数据量是成反比的,当数据量越大时,他的作用就越小。确切的说,刚开始时随着数据量的增大其对数据库查询的优化作用会逐渐增大;但是,当数据数量累积到一定程度时,其效果就会逐渐减小。当数据量达到一定的程度,如一百万条时,索引的作用就非常微小了。
针对这种大容量记录的表,若需要查询,其查询效率不高。为此,数据库该采用什么方式来提高这个大表的查询效率呢?
这两大数据库不约而同的采用了哈希族的方式,来提高大表的查询。
如现在在设计一个图书馆管理系统,这个系统中,读者的信息有几百万、几千万条。当读者的信息存储在一个普通表中的时候,这些记录按照存储到数据库中的先后顺序,物理地保存到分配的块中。也就是说,数据库服务器的数据文件,或者数据表,就好像一个个抽屉,数据库是按先后顺序一条记录一条记录地从上到下存放数据。当整个表的容量逐渐增加时,该表相应的速度就会非常慢。
在刚开始的时候,人们想到了利用镞表的方式来提高这个性能。也就是说,把整个抽屉分成几排,然后每排给他们归一类,如按办图书卡时的年龄进行分类,10岁以下的一类,10岁到15岁的一类等等。如此的话,在存读者信息的时候,就不会简单的按照办卡时间来存储,而是按照类别来存储。如果是属于10岁到15岁整个类,就会被物理的存储在同一个系列的块中。如此的话,就可以分类查找信息的速度。如果可以按类别查找数据信息,速度会非常快。
但是,随着数据库中的镞块增加,会影响数据库的整体运行性能。这个问题发生之后,数据库开发人员又想到了利用哈希函数来解决这个问题。哈希函数将会给定一个数值用来限定镞块数的数量的预计范围。
也就是说,现在我们要建立一个图书馆用户的表格,我们可以利用图书卡的卡号作为镞主键将有利于数据的存储分布。但是,当读者增加时,就需要使用一个哈希函数来约束镞块的数量。
不过Oracle数据库在使用镞技术来优化大表数据查询之外,还采用了另外一种独有的技术,即分区表的形式,来提高用户对于大表的查询效率。
在Oracle数据库中,可以将一个大表分开放置在几个逻辑分区中,或者是将一个大表分成几张小表。在查询时,即可以单独的对这些小表进行查询,而且,也可以利用union all参数进行一起查询。
如在设计销售订单管理系统时,我们可以按年度把销售订单表分割成几张小表,如此的话,后续的查询效率会比一张大表高很多。不过,这个技术的应用,关键在于如何对表进行分割,以及如何把表放置在几个逻辑分区中,这需要有一定经验的数据库设计工程师才能设计出一个好的方案。关于这方面的内容,在后续的文章中,笔者会有所阐述。