Chinaunix首页 | 论坛 | 博客
  • 博客访问: 432897
  • 博文数量: 239
  • 博客积分: 8010
  • 博客等级: 中将
  • 技术积分: 2431
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-02 21:12
文章分类
文章存档

2008年(239)

我的朋友

分类:

2008-06-17 23:47:19

排序处理

系统对SQL语句的处理可能需要进行排序。这主要是由于以下两个原因引起的:

1)在SQL语句中,指定要对结果集进行排序,或者包含需要排序的关键字。

2)进行表连接时,系统选用排序归并连接、散列连接;或者系统虽然选用嵌套循环连接,但发现作为输入的表如果已排序,其实现效率会更高。有关表连接的详细信息,可参见第5.3.2一节。

如果在要排序的字段上存在索引,系统就直接使用该索引,顺序读取表,从而完成排序。如果在要排序的字段上不存在索引,或者尽管存在索引,但按照索引访问需要更多的系统开销时,系统就不会使用索引,只是在最后,基于此字段对结果集进行排序。

如果要排序的数据,可以一次在内存中完成,这种排序就称为内排序。如果由于内存空间限制,无法一次完成数据的排序,系统就按照可用内存的空间大小,将要排序数据分成多个部分、分别排序,中间结果被存放在磁盘上,最后将多个已排序结果集合并,形成最终的结果集,这种排序称为外排序。

很显然,内排序的执行效率很高。如果数据库中存在排序操作,我们当然希望所有的排序均能够一次在内存中完成。

SQL语句中出现下列的关键字后,如果优化器没有选用相关的索引,就一定会进行排序操作。

 

1. order by

 

该关键字要求对结果集进行排序。如果表中的某些字段经常在order by中使用,在这些字段上建立索引将有助于避免数据库中的排序操作。

 

2. group by

 

该关键字要求对结果集进行分组。系统对分组的处理,是首先基于要分组的字段进行排序,然后对已排序的记录数据,从上到下采取以下的处理步骤,形成结果集:

1)取出第一条记录,放入结果集。

2)取出下一条记录。如果该条记录和结果集中最后一条记录在要分组字段上取值相等,就将该条记录和最后一条记录合并;如果不相等,就将该记录放在结果集的最后面。

3)继续处理,直到所有的记录被处理完成。

例如,下面SQL语句返回各部门中员工的月工资总额:

SELECT dept_no, sum(empy_salary)

FROM employee group by dept_no

系统首先对员工表employee基于部门号dept_no进行排序。然后对已经排序的记录集,按照字段dept_no的值,将字段empy_salary中的值相加。

 

3. distinct

 

该关键字要求结果集中不能有重复的记录。系统对distinct的处理,类似于对group by的处理。系统首先按照结果集中要求的字段进行排序,然后按照以下步骤剔除重复的记录。

1)取出第一条记录,放入结果集。

2)取出下一条记录。如果该条记录和结果集中最后一条记录相同,就放弃该条记录;如果不相同,就将该记录放在结果集的最后面。

3)继续处理,直到所有的记录被处理完成。

例如,下面SQL语句从员工表employee中返回所有的部门号:

SELECT distinct dept_no

FROM employee

系统首先读取表employee中的所有记录,基于字段dept_no进行排序。然后对已经排序的记录集,按照字段dept_no的值,删除重复的记录。

 

4. 集合操作:unionintersectminus

 

集合操作:unionintersectminus,用来实现了两个记录集之间的并、交、差运算,其中:

1union:合并两个记录集,结果集中不能有重复的记录。

2intersect:返回同时出现在两个记录集中的记录。

3minus:返回出现在第一个记录集,而不在第二个记录集的所有记录。

对于这些集合运算,系统首先将两个记录集基于相同的字段或者字段组合,分别按照相同的方向排序,然后将这两个已经排序的记录集合从上到下进行比较,从而找到最终的结果集。

这里,我们需要注意关键字unionunion all的区别。union all允许结果集中有重复的记录,因此优化器不会要求对记录集进行排序。

阅读(704) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~