分类:
2008-05-17 16:53:26
| |
在这个查询中,找出报纸单价为0.5元的收订员名单。下层查询返回一组值给上层查询,然后由上层查询块再根据下层块提供的值继续查询。在这种嵌套查询中,对上层查询的每一个值OrderNo,下层查询都要对表OrderDetail进行全部扫描,执行效率显然不会高。在该查询中,有2层嵌套,如果每层都查询1000行,那么这个查询就要查询100万行数据。在系统开销中,对表Order的扫描占82%,对表OrderDetail的搜索占16%。如果我们用来代替,即:
那么对表Order的扫描占74%,对表OrderDetail的搜索占14%。 而且,一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。 4、通配符 在SQL语句中,LIKE关键字支持通配符匹配,但这种匹配特别耗费时间。例如:SELECT * FROM Order WHERE CreateUser LIKE ‘M_ _ _’ 。即使在CreateUser字段上建立了索引,在这种情况下也还是采用顺序扫描的方式,Order表中有1000条记录,就需要比较1000次。如果把语句改为SELECT * FROM Order WHERE CreateUser >’M’ AND CreateUser <’N’,在执行查询时就会利用索引来查询,显然会大大提高。 5、distinct 使用distinct是为了在结果集中不出现重复值,但是distinct会产生一张工作表,并进行排序来删除重复记录,这会大大增加查询和I/O的操作次数。因此应当避免使用distinct关键字。 6、负逻辑 负逻辑如!=、<>、not in等,都会导致DB2用表扫描来完成查询。当表较大时,会影响系统性能,可以用别的操作来代替。 7、临时表 使用临时表时数据库会在磁盘中建立相应的数据结构,因为内存的访问速度远远大于外部存储器的访问速度,在复杂查询中使用临时表时,中间结果会被导入到临时表中,这种磁盘操作会大大降低查询效率。另外,在分布式系统中,临时表的使用还会带来多个查询进程之间的同步问题。所以,在进行复杂查询时最好不要使用临时表。 8、存储过程 DB2中的Stored Procedure Builder可以产生存储过程,运行并测试存储过程。存储过程可以包含巨大而复杂的查询或SQL操作,经过编译后存储在DB2数据库中。用户在多次使用同样的SQL操作时,可以先把这些SQL操作做成存储过程,在需要用到的地方直接引用其名字进行调用。存储过程在第一次执行时建立优化的查询方案,DB2将查询方案保存在高速缓存里,以后调用运行时可以直接从高速缓存执行,省去了优化和编译的阶段,节省了执行时间,从而提高效率和系统利用率。 最优的查询方案按照某些标准选择往往不可行,要根据实际的要求和具体情况,通过比较进行选择。DB2提供的Query Patroller可以对不同的查询方案的查询代价进行比较,通过追踪查询语句,返回查询不同阶段的系统开销,从而作出最佳选择。DB2提供的Performance Monitor也对整个数据库系统的性能进行监控,包括I/O时间、查询次数、排序时间、同步读写时间等等。 数据库系统的并发控制也能影响系统性能。多个用户的同时操作可能导致数据的不一致性,DB2为了防止同时修改造成数据丢失和访问未被提交的数据,以及数据的读,采用Lock机制来实现控制。 DB2中可以对表空间、表、表列和索引加锁。锁的粒度越大,锁越简单,开销小,并发度低;粒度小,锁机制复杂,开销大,并发度高。大型系统在并发处理中如果遇到所要分配的资源处于锁定状态,系统会把进程挂起。如果一个很耗时的查询操作工作于一个经常使用的表上,此时使用表一级锁,意味着整个系统都要等待你的查询结束以后才能够继续运行。所以在复杂查询中,尽量避免使用表一级锁。如果有这一类的需要该怎么办呢?可以利用视图来解决这一类问题。视图避免了对表的直接操作,同时有能够保证数据库的高效运转。 |