- 浏览: 635845 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (213)
- JAVA (53)
- Tomcat (14)
- EXTJS专栏 (2)
- 数据库 (23)
- JavaScript (13)
- jQuery (11)
- 需求分析 (2)
- css (1)
- 手机 (1)
- php (7)
- 生活 (1)
- ssh (11)
- JFReeChart (2)
- Delphi (1)
- junit (0)
- liunx (10)
- 项目管理 (11)
- 文件下载 (1)
- Eclipse (2)
- jsp (2)
- 外挂、游戏 (1)
- 面试题 (8)
- 性能测试 (2)
- apache (1)
- MyBatis (1)
- Webservice (2)
- ant (1)
- IDEA (2)
- log4j (1)
- 小程序 (1)
最新评论
-
hll127:
请问service这个方法里为什么要while(true)啊? ...
jsp页面静态化例子 -
tarena1:
Spring 源码解读 推荐流程 -
konglx:
springaop_springmvc 写道可以参考最新的文档 ...
Web项目添加Maven支持步骤 -
springaop_springmvc:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
Web项目添加Maven支持步骤 -
9976:
很好,谢谢
Spring 源码解读 推荐流程
一、概述
这篇文章是数据库性能调优技术的第二篇。上一篇讲解的索引调优是数据库性能调优技术的基础。这篇讲解的深入理解单表执行计划,是数据库性能调优的有力工具。
查询语句可以有多种可选执行计划,如何选择效率最高的执行计划?达梦数据库、oracle数据库、sql server数据库都是采用基于成本的查询优化,对备选执行计划进行打分,选择大家最小的执行计划进行执行。这些内容,我会在后续的几篇文章中进行详细的描述。在此之前,我们首先需要掌握如何理解数据库执行计划。这篇文章讲解只涉及单表操作的执行计划。
达梦数据库、oracle数据库、sql server数据库都可以显示给定语句的执行计划。我详细分析了这三个数据库的执行计划,三者之间并无本质区别。
所以本文的内容适合于这三个数据库。同样,也应该适合绝大多数其它的数据库。
单表执行的深入理解,是了解多表执行计划的基础。达梦数据库显示的执行计划时,显示的信息会多一些。
因此,这篇文章中我选择达梦数据库作为实例数据库来讲解执行计划的原理。
读完本文后,应该能够读懂这三个数据库的单表执行计划。
二、深入理解数据库执行计划
达梦数据库的执行计划有两种显示方式:第一种为图形化的显示方式;第二种为文本式的显示方式。这里采用第二种方式进行讲解。
理解执行计划,是迈向理解数据库性能调优的重要一步。从执行计划中,我们可以看出数据库是如何执行查询语句,并根据执行计划判断出该查询语句的执行是否高效,以及如何进行优化。
下面我们将通过一些例子来理解数据库执行计划。
1.没有索引的全表扫描过滤如何执行?
构造处执行场景:
create table t1(c1 int,c2 int);
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t1 values(3,3);
insert into t1 values(4,4);
insert into t1 values(5,5);
insert into t1 values(6,6);
查询语句为:
select * from t1 where c1=2;
该语句的执行过程,如果用语言描述可以描述成这样:
1)如果是第一次执行该步骤,则取得表的第一条记录;否则取得当前记录的下一条记录。如果记录已经扫描结束,则执行步骤4,否则执行步骤2。
2)判断该记录是否满足过滤条件c1=2,满足则执行步骤3,否则执行步骤1。
3)把该记录放到结果集中,执行步骤1。
4)将结果集返回给客户端。
实际上,数据库执行查询语句的过程也是类似的,下面是该查询语句的执行计划:
#RSET:[21, 1, 1];
#XFLT:[0, 0, 0]; EXPR0 = 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
该执行计划中出现的内容,在此做出解释:
1)CSEK(查找)类似于上文中描述的步骤1,方括号中的内容是执行该操作的评估代价,本文不作分析。“INDEX33555545(T1)”说明使用了T1表的聚集索引,“FULL_SCAN”表示对聚集索引INDEX33555545(T1)进行全扫描。
这里需要注意的是,达梦数据库中的表默认情况下是索引组织的。如果建表时指定了cluster primary key,那么数据以该clsuter primary key组织数据,否则以rowid组织数据。
2)XFLT(过滤)类似于上文中描述的步骤2,“EXPR0 = 2”是过滤条件。
3)RSET(结果集)类似于上文中描述的步骤3,用来存放符合条件的记录集。
我们可以看出,数据库的执行过程和我们用语言描述的步骤是一致的。
该查询语句完整的执行流程如下:
1)CSEK取得第一条记录(1,1)传给XFLT,将控制权传给XFLT。
2)XFLT发现该记录(1,1)不符合条件,将控制权传给CSEK。
3)CSEK取得下一条记录(2,2)传给XFLT,将控制权传给XFLT。
4)XFLT发现记录(2,2)符合条件,将该记录传给RSET,将控制权传给RSET。
5)RSET将记录(2,2)放入结果集,将控制权传给XFLT。
6)XFLT给控制权传给CSEK。
7)CSEK取得下一条(3,3)传给XFLT,将控制权传给XFLT。
8)XFLT发现该记录(3,3)不符合条件,将控制权传给CSEK。
9)CSEK取得下一条(4,4)传给XFLT,将控制权传给XFLT。
10)XFLT发现该记录(4,4)不符合条件,将控制权传给CSEK
11)CSEK取得下一条(5,5)传给XFLT,将控制权传给XFLT。
12)XFLT发现该记录(5,5)不符合条件,将控制权传给CSEK。
13)CSEK取得下一条(6,6)传给XFLT,将控制权传给XFLT。
14)XFLT发现该记录(6,6)不符合条件,将控制权传给CSEK。
15)CSEK发现描述操作已经结束,通知XFLT结束。将控制权传给XFLT。
16)XFLT得知查询操作结束,通知RSET结束。将控制权传给RSET。
17)RSET得知操作结束。
18)发送结果集(包含记录(2,2))给客户端。
2.如果表t1上的c1列有非唯一索引,如何执行呢?
表t1的定义以及数据和1中描述的一样。
创建索引:
create index it1c1 on t1(c1);
查询语句“select * from t1 where c1=2;”对应的执行计划为:
#RSET:[201, 2, 1];
#CSEK(SECOND):[201, 2, 1]; IT1C1(T1), INDEX_EQU_SEARCH
CSEK行的“SECOND”表示使用非聚集索引“IT1C1”,对该索引进行索引等值(INDEX_EQU_SEARCH)查找。
该执行计划的执行流程为:
1)CSEK使用c1=2查找非聚集索引,得到第一条c1=2的索引记录(2,rowid1)中的rowid1(为数值)。使用rowid1查找聚集索引得到对应的数据记录(2,2)传递给RSET,将控制权传给RSET。
2)RSET将记录(2,2)放入结果集,将控制权传给CSEK。(因为c1上的索引是非唯一的,所以可能出现两条以上的记录满足c1=2,所以需要将控制权传给CSEK)。
3)CSEK取得当前非聚集记录的下一条记录(3,rowid2),因为3!=2,所以扫描结束。将控制权传给RSET。(如果满足c1=2的记录数大于1条,需要继续传递记录给RSET,以此类推,直到遇到不满足c1=2的那条记录,结束操作。)
4)RSET得知操作结束。
5)发送结果集(包含记录(2,2))给客户端。
3.如果表t1上的c1列有唯一索引,如何执行呢?
首先删除c1列上的非唯一索引,然后在c1列上创建唯一索引:
drop index it1c1;
create unique index uit1c1 on t1(c1);
查询语句“select * from t1 where c1=2;”对应的执行计划为:
#RSET:[201, 2, 1];
#CSEK(SECOND):[201, 2, 1]; UIT1C1(T1), INDEX_EQU_SEARCH
该执行计划的执行流程为:
1)CSEK使用c1=2查找非聚集索引,得到c1=2的索引记录(2,rowid1)中的rowid1(为数值)。使用rowid1查找聚集索引得到对应的数据记录(2,2)传递给RSET,将控制权传给RSET。(当然,有人也许会问,如果没有记录满足c1=2怎么办呢?那么,此处什么记录都不传递给RSET,通知RSET查询操作结束,最后返回空集给客户端)。
2)RSET将记录(2,2)放入结果集,操作结束(因为是唯一索引,所以最多只有1条记录满足c1=2)。
3)发送结果集(包含记录(2,2))给客户端。
这里我们发现,例3使用了唯一索引,例2使用了非唯一索引。例3的执行速度大于例2的执行速度。
4.如何理解执行计划中的top n操作?
查询语句“select top 10 * from t1 where c1〉2;”对应的执行计划为:
#RSET:[21, 1, 1];
#XTOP:[0, 0, 0]; top_off(0), top_num(10)
#XFLT:[0, 0, 0]; EXPR1 〉 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
XTOP(取得前N条记录):将XFLT操作符传递来的记录放入到RSET(结果集)中,并判断记录数是否已经等于给定值10(语句中的top 10)。如果已经等于10,则查询已经执行成功,退出。否则将控制权限传给XFLT,继续执行。依次执行,直到取得10条记录,或者表CSEK操作已经查询结束(即符合条件的记录不满10条)。
5.如何理解执行计划中的order by操作?
查询语句“select top 10 * from t1 where c2〉2 order by c1;”对应的执行计划为:
#RSET:[21, 1, 1];
#XSORT:[0, 0, 0]; keys_num(1), is_distinct(FALSE)
#XFLT:[0, 0, 0]; EXPR1 〉 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
XSORT(对记录进行排序):将XFLT操作符传递来的记录插入到XSORT维护的临时空间中的合理位置,按c1进行有序排列。然后将控制权传给XFLT以取得下一条符合条件的记录。等处理完所有符合条件的记录。XSORT操作符才会将控制权限传给RSET。
6.是不是查询语句中一旦出现order by字句,执行计划中就会出现XSORT操作符?
不是。
比如,查询语句“select c1 from t1 order by c1;”对应的执行计划为:
#RSET:[0, 0, 0];
#CSEK:[0, 0, 0]; UIT1C1(T1), FULL_SCAN
从执行中我们可以看出,达梦直接对索引UIT1C1进行全索引扫描,对于得到的每一条记录不需要进行XSORT排序操作,直接放入RSET(结果集)中。因为索引UIT1C1本身就是按照c1进行排序的。
7.有文档说,对于语句“select max(c1) from t1”,可以在c1列上创建索引从而查询速度变快。那么在执行计划中是如何体现的呢?
查询语句“select max(c1) from t1”对应的执行计划:
#RSET:[0, 0, 0];
#XEVL:[0, 0, 0];
#FAGR:[0, 0, 0]; function_num(1)
在这个执行计划中,我们没有看到CSEK操作符。因为c1上存在索引UIT1C1,该索引叶子节点的最右端就是c1的最大值。FARG直接返回该最大值。语句“select min(c1) from t1;”、语句“select count(*) from t1;”的执行原理一样。XEVL是表达式计算,本文不进行讲解。
8.如果列上存在索引,如何理解中的group by操作?
查询语句“select c1,count(*) from t1 where c1〉=2 group by c1;”对应的执行计划为:
#RSET:[11, 1, 1];
#XEVL:[0, 0, 0];
#SAGR:[0, 0, 0]; group_by_num(1), function_num(1)
#CSEK:[11, 1, 1]; UIT1C1(T1), INDEX_GE_SEARCH
我们可以得到,CSEK使用了索引UIT1C1进行了范围查找。首先传递给SARG的是连续的c1=2的记录组,然后是c1=3的记录组,然后是c1=4的记录组,……
此处SARG的执行流程是
1)从CSEK取得一条c1=2记录,将计数加1,
2)从CSEK取得下一条记录,如果该记录满足c1,将计数+1。
3)重复执行步骤2,直到取得第一条不满足c1=2的记录,将(2,对应的计算)传递给XEVL,再传给RSET(结果集)。接着对c1=3的记录组执行同样的流程。依此类推,直到处理完所有符合条件的记录。
这里我们的分组函数是count(*),如果是其它的分组函数,处理过程类似。
9.如果列上不存在索引,如何理解中的group by操作?
查询语句“select c2,count(*) from t1 where c2〉=2 group by c2;”对应的执行计划为:
#RSET:[21, 1, 1];
#XEVL:[0, 0, 0];
#HAGR:[0, 0, 0]; group_by_num(1), function_num(1)
#XFLT:[0, 0, 0]; EXPR0 〉= 2
#CSEK:[21, 1, 1]; INDEX33555550(T1), FULL_SCAN
这里因为c2上没有索引,HARG的作用是HASH分组。
HARG的执行流程是:
1)从XFLT取得一条记录
2)记录的c1=m,如果在hash表中已经对应项,计数+1,如果不存在对应项,在创建一个新的hash项。
3)所有的符合过滤条件的记录处理完成之后,HARG才会将控制权限传给上层操作符,HARG每次向上层操作符传递一条(m,m对应的计数)。
这里我们的分组函数是count(*),如果是其它的分组函数,处理过程类似。
这篇文章是数据库性能调优技术的第二篇。上一篇讲解的索引调优是数据库性能调优技术的基础。这篇讲解的深入理解单表执行计划,是数据库性能调优的有力工具。
查询语句可以有多种可选执行计划,如何选择效率最高的执行计划?达梦数据库、oracle数据库、sql server数据库都是采用基于成本的查询优化,对备选执行计划进行打分,选择大家最小的执行计划进行执行。这些内容,我会在后续的几篇文章中进行详细的描述。在此之前,我们首先需要掌握如何理解数据库执行计划。这篇文章讲解只涉及单表操作的执行计划。
达梦数据库、oracle数据库、sql server数据库都可以显示给定语句的执行计划。我详细分析了这三个数据库的执行计划,三者之间并无本质区别。
所以本文的内容适合于这三个数据库。同样,也应该适合绝大多数其它的数据库。
单表执行的深入理解,是了解多表执行计划的基础。达梦数据库显示的执行计划时,显示的信息会多一些。
因此,这篇文章中我选择达梦数据库作为实例数据库来讲解执行计划的原理。
读完本文后,应该能够读懂这三个数据库的单表执行计划。
二、深入理解数据库执行计划
达梦数据库的执行计划有两种显示方式:第一种为图形化的显示方式;第二种为文本式的显示方式。这里采用第二种方式进行讲解。
理解执行计划,是迈向理解数据库性能调优的重要一步。从执行计划中,我们可以看出数据库是如何执行查询语句,并根据执行计划判断出该查询语句的执行是否高效,以及如何进行优化。
下面我们将通过一些例子来理解数据库执行计划。
1.没有索引的全表扫描过滤如何执行?
构造处执行场景:
create table t1(c1 int,c2 int);
insert into t1 values(1,1);
insert into t1 values(2,2);
insert into t1 values(3,3);
insert into t1 values(4,4);
insert into t1 values(5,5);
insert into t1 values(6,6);
查询语句为:
select * from t1 where c1=2;
该语句的执行过程,如果用语言描述可以描述成这样:
1)如果是第一次执行该步骤,则取得表的第一条记录;否则取得当前记录的下一条记录。如果记录已经扫描结束,则执行步骤4,否则执行步骤2。
2)判断该记录是否满足过滤条件c1=2,满足则执行步骤3,否则执行步骤1。
3)把该记录放到结果集中,执行步骤1。
4)将结果集返回给客户端。
实际上,数据库执行查询语句的过程也是类似的,下面是该查询语句的执行计划:
#RSET:[21, 1, 1];
#XFLT:[0, 0, 0]; EXPR0 = 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
该执行计划中出现的内容,在此做出解释:
1)CSEK(查找)类似于上文中描述的步骤1,方括号中的内容是执行该操作的评估代价,本文不作分析。“INDEX33555545(T1)”说明使用了T1表的聚集索引,“FULL_SCAN”表示对聚集索引INDEX33555545(T1)进行全扫描。
这里需要注意的是,达梦数据库中的表默认情况下是索引组织的。如果建表时指定了cluster primary key,那么数据以该clsuter primary key组织数据,否则以rowid组织数据。
2)XFLT(过滤)类似于上文中描述的步骤2,“EXPR0 = 2”是过滤条件。
3)RSET(结果集)类似于上文中描述的步骤3,用来存放符合条件的记录集。
我们可以看出,数据库的执行过程和我们用语言描述的步骤是一致的。
该查询语句完整的执行流程如下:
1)CSEK取得第一条记录(1,1)传给XFLT,将控制权传给XFLT。
2)XFLT发现该记录(1,1)不符合条件,将控制权传给CSEK。
3)CSEK取得下一条记录(2,2)传给XFLT,将控制权传给XFLT。
4)XFLT发现记录(2,2)符合条件,将该记录传给RSET,将控制权传给RSET。
5)RSET将记录(2,2)放入结果集,将控制权传给XFLT。
6)XFLT给控制权传给CSEK。
7)CSEK取得下一条(3,3)传给XFLT,将控制权传给XFLT。
8)XFLT发现该记录(3,3)不符合条件,将控制权传给CSEK。
9)CSEK取得下一条(4,4)传给XFLT,将控制权传给XFLT。
10)XFLT发现该记录(4,4)不符合条件,将控制权传给CSEK
11)CSEK取得下一条(5,5)传给XFLT,将控制权传给XFLT。
12)XFLT发现该记录(5,5)不符合条件,将控制权传给CSEK。
13)CSEK取得下一条(6,6)传给XFLT,将控制权传给XFLT。
14)XFLT发现该记录(6,6)不符合条件,将控制权传给CSEK。
15)CSEK发现描述操作已经结束,通知XFLT结束。将控制权传给XFLT。
16)XFLT得知查询操作结束,通知RSET结束。将控制权传给RSET。
17)RSET得知操作结束。
18)发送结果集(包含记录(2,2))给客户端。
2.如果表t1上的c1列有非唯一索引,如何执行呢?
表t1的定义以及数据和1中描述的一样。
创建索引:
create index it1c1 on t1(c1);
查询语句“select * from t1 where c1=2;”对应的执行计划为:
#RSET:[201, 2, 1];
#CSEK(SECOND):[201, 2, 1]; IT1C1(T1), INDEX_EQU_SEARCH
CSEK行的“SECOND”表示使用非聚集索引“IT1C1”,对该索引进行索引等值(INDEX_EQU_SEARCH)查找。
该执行计划的执行流程为:
1)CSEK使用c1=2查找非聚集索引,得到第一条c1=2的索引记录(2,rowid1)中的rowid1(为数值)。使用rowid1查找聚集索引得到对应的数据记录(2,2)传递给RSET,将控制权传给RSET。
2)RSET将记录(2,2)放入结果集,将控制权传给CSEK。(因为c1上的索引是非唯一的,所以可能出现两条以上的记录满足c1=2,所以需要将控制权传给CSEK)。
3)CSEK取得当前非聚集记录的下一条记录(3,rowid2),因为3!=2,所以扫描结束。将控制权传给RSET。(如果满足c1=2的记录数大于1条,需要继续传递记录给RSET,以此类推,直到遇到不满足c1=2的那条记录,结束操作。)
4)RSET得知操作结束。
5)发送结果集(包含记录(2,2))给客户端。
3.如果表t1上的c1列有唯一索引,如何执行呢?
首先删除c1列上的非唯一索引,然后在c1列上创建唯一索引:
drop index it1c1;
create unique index uit1c1 on t1(c1);
查询语句“select * from t1 where c1=2;”对应的执行计划为:
#RSET:[201, 2, 1];
#CSEK(SECOND):[201, 2, 1]; UIT1C1(T1), INDEX_EQU_SEARCH
该执行计划的执行流程为:
1)CSEK使用c1=2查找非聚集索引,得到c1=2的索引记录(2,rowid1)中的rowid1(为数值)。使用rowid1查找聚集索引得到对应的数据记录(2,2)传递给RSET,将控制权传给RSET。(当然,有人也许会问,如果没有记录满足c1=2怎么办呢?那么,此处什么记录都不传递给RSET,通知RSET查询操作结束,最后返回空集给客户端)。
2)RSET将记录(2,2)放入结果集,操作结束(因为是唯一索引,所以最多只有1条记录满足c1=2)。
3)发送结果集(包含记录(2,2))给客户端。
这里我们发现,例3使用了唯一索引,例2使用了非唯一索引。例3的执行速度大于例2的执行速度。
4.如何理解执行计划中的top n操作?
查询语句“select top 10 * from t1 where c1〉2;”对应的执行计划为:
#RSET:[21, 1, 1];
#XTOP:[0, 0, 0]; top_off(0), top_num(10)
#XFLT:[0, 0, 0]; EXPR1 〉 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
XTOP(取得前N条记录):将XFLT操作符传递来的记录放入到RSET(结果集)中,并判断记录数是否已经等于给定值10(语句中的top 10)。如果已经等于10,则查询已经执行成功,退出。否则将控制权限传给XFLT,继续执行。依次执行,直到取得10条记录,或者表CSEK操作已经查询结束(即符合条件的记录不满10条)。
5.如何理解执行计划中的order by操作?
查询语句“select top 10 * from t1 where c2〉2 order by c1;”对应的执行计划为:
#RSET:[21, 1, 1];
#XSORT:[0, 0, 0]; keys_num(1), is_distinct(FALSE)
#XFLT:[0, 0, 0]; EXPR1 〉 2
#CSEK:[21, 1, 1]; INDEX33555545(T1), FULL_SCAN
XSORT(对记录进行排序):将XFLT操作符传递来的记录插入到XSORT维护的临时空间中的合理位置,按c1进行有序排列。然后将控制权传给XFLT以取得下一条符合条件的记录。等处理完所有符合条件的记录。XSORT操作符才会将控制权限传给RSET。
6.是不是查询语句中一旦出现order by字句,执行计划中就会出现XSORT操作符?
不是。
比如,查询语句“select c1 from t1 order by c1;”对应的执行计划为:
#RSET:[0, 0, 0];
#CSEK:[0, 0, 0]; UIT1C1(T1), FULL_SCAN
从执行中我们可以看出,达梦直接对索引UIT1C1进行全索引扫描,对于得到的每一条记录不需要进行XSORT排序操作,直接放入RSET(结果集)中。因为索引UIT1C1本身就是按照c1进行排序的。
7.有文档说,对于语句“select max(c1) from t1”,可以在c1列上创建索引从而查询速度变快。那么在执行计划中是如何体现的呢?
查询语句“select max(c1) from t1”对应的执行计划:
#RSET:[0, 0, 0];
#XEVL:[0, 0, 0];
#FAGR:[0, 0, 0]; function_num(1)
在这个执行计划中,我们没有看到CSEK操作符。因为c1上存在索引UIT1C1,该索引叶子节点的最右端就是c1的最大值。FARG直接返回该最大值。语句“select min(c1) from t1;”、语句“select count(*) from t1;”的执行原理一样。XEVL是表达式计算,本文不进行讲解。
8.如果列上存在索引,如何理解中的group by操作?
查询语句“select c1,count(*) from t1 where c1〉=2 group by c1;”对应的执行计划为:
#RSET:[11, 1, 1];
#XEVL:[0, 0, 0];
#SAGR:[0, 0, 0]; group_by_num(1), function_num(1)
#CSEK:[11, 1, 1]; UIT1C1(T1), INDEX_GE_SEARCH
我们可以得到,CSEK使用了索引UIT1C1进行了范围查找。首先传递给SARG的是连续的c1=2的记录组,然后是c1=3的记录组,然后是c1=4的记录组,……
此处SARG的执行流程是
1)从CSEK取得一条c1=2记录,将计数加1,
2)从CSEK取得下一条记录,如果该记录满足c1,将计数+1。
3)重复执行步骤2,直到取得第一条不满足c1=2的记录,将(2,对应的计算)传递给XEVL,再传给RSET(结果集)。接着对c1=3的记录组执行同样的流程。依此类推,直到处理完所有符合条件的记录。
这里我们的分组函数是count(*),如果是其它的分组函数,处理过程类似。
9.如果列上不存在索引,如何理解中的group by操作?
查询语句“select c2,count(*) from t1 where c2〉=2 group by c2;”对应的执行计划为:
#RSET:[21, 1, 1];
#XEVL:[0, 0, 0];
#HAGR:[0, 0, 0]; group_by_num(1), function_num(1)
#XFLT:[0, 0, 0]; EXPR0 〉= 2
#CSEK:[21, 1, 1]; INDEX33555550(T1), FULL_SCAN
这里因为c2上没有索引,HARG的作用是HASH分组。
HARG的执行流程是:
1)从XFLT取得一条记录
2)记录的c1=m,如果在hash表中已经对应项,计数+1,如果不存在对应项,在创建一个新的hash项。
3)所有的符合过滤条件的记录处理完成之后,HARG才会将控制权限传给上层操作符,HARG每次向上层操作符传递一条(m,m对应的计数)。
这里我们的分组函数是count(*),如果是其它的分组函数,处理过程类似。
发表评论
-
ORACLE 索引原理
2013-03-25 21:40 1087B-TREE索引 一个B树索引只有一个根节点,它实际就 ... -
oracle笔记1-序列
2012-12-14 10:08 900建立sequence时注意:Cache Size 至少要设置为 ... -
in与exist , not in与not exist 的区别
2011-12-19 11:31 1052in和exists in 是把外表和 ... -
Oracle SQL性能优化
2011-12-17 20:38 826(1) 选择最有效率的表名顺序(只在基于规则的优化器 ... -
SQL Server 2005 Express 远程连接 客户端 远程访问 设置 全攻略 (适用 SQL Server 2005 其他版本)
2011-05-01 12:12 2756SQL Server 2005 Express 是微软提供的数 ... -
行级触发器对当前表操作,”ORA-04091: 表 COMPANY 发生了变化, 触发器/函数不能读它“,解决方法
2011-03-07 15:12 4545行级触发器对当前表操作,”ORA-04091: 表 ... -
启动mssql远程TCP/IP访问权限
2011-01-03 21:17 1350如果想mssql能通过远程访问或是myeclipse能访问,需 ... -
oracle替换clob类型中的一段数据
2010-11-02 11:35 1980CREATE OR REPLACE FUNCTION dfn_ ... -
Sql 批量替换所有表中内容
2010-11-02 09:30 1111declare @t varchar(255),@c varc ... -
删除所有表中数据
2010-11-02 09:28 1177最近一个项目中作结合测试,需要测试数据流的正确性,这就需要在执 ... -
Ms Sql SErver 2000和2005数据互导
2010-08-20 22:26 1624因为数据库附加到2005的时候, 数据库文件已经自动升级到20 ... -
某个数据文件损坏,如何打开数据库?
2010-04-19 11:05 1538某个数据文件损坏,如何打开数据库? 系统环境: 1、 ... -
增大oracle重做日志的大小
2010-03-26 21:09 4556重做日志(redo log)是由LGWR来进行控制的。Orac ... -
MySQL外键
2010-02-27 11:26 1071定义数据表 假如某个电脑生产商,它的数据库中保存着整机和 ... -
mysql乱码解决
2010-01-23 14:45 871在mysql的my.ini文件中增加以下配置: 1、 [m ... -
如何查看oracle表空间
2009-11-14 11:01 2947select tablespace_name,sum(byte ... -
ORA-04031: 无法分配 12519000 字节的共享内存 ("large pool","unknown object","hash-join subh"
2009-10-20 16:51 8641ORA-04031: 无法分配 12519000 字节的共享内 ... -
ORACLE中的物化视图
2009-08-27 21:19 1019物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副 ... -
我整理的关于P4安装ORACLE解决方法
2009-08-18 11:35 1591我整理的关于P4安装ORACLE解决方法 P4的计算机最好安 ... -
创建用户
2009-06-23 22:26 1169/*--示例说明 示例在数据库pubs中创建一个 ...
相关推荐
数据库性能调优技术2深入理解单表执行计划,对单表执行计划详细分析
学习ORACLE时的一些资料,分享给大家,共勉! 上一篇文章讲解了深入了解单表执行计划,单表执行计划是理解多表执行计划的基础,文章中主要讲解嵌套循环连接。
执行计划可以辅助我们写出高效率的T-SQL代码,同时也可以找出现有T-SQL代码的问题,还可以监控数据库!当然,最后如何使用执行计划还是取决于我们自己了,但是不管怎么样,我们首先学会解析执行计划中所包含的信息,...
11.2 通过解释工具分析SQL语句执行计划 11.3 理解SQL语句如何工作 11.4 SQL调优案例 11.5 提高应用程序性能 第12章 DB2调优案例、问题总结和技巧 12.1 调优案例一:某移动公司存储设计不当和SQL引起的I/O瓶颈 12.2 ...
有近20年使用Oracle技术产品以及Oracle数据库管理员/Oracle数据库应用管理员的经验,是真正应用集群、性能调优以及数据库内部属性方面的专家。同时是一位演讲家及Oracle ACE。 JARED STILL 从1994年就开始使用...
例如,当我们点一个数据库的表,所有和此表相关的索引、约束、存储过程、SQL语句以及和其他表的相互引用关系都在同一界面显示出来。为了简化操作,用户可以在浏览窗口操作数据库对象。 SQL 编辑器: SQL 编辑器的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
Azkaban是一个用Java编写的开源工作流管理系统,旨在简化大数据处理过程中的任务调度和工作流程管理。...同时,编译源代码还有助于用户深入理解系统的工作原理和内部机制,从而更好地进行系统调优和故障排除。
│ Java面试题67:数据库优化之数据库表设计遵循范式.mp4 │ Java面试题68:选择合适的数据库引擎.mp4 │ Java面试题69:选择合适的索引.mp4 │ Java面试题70:使用索引的一些技巧.mp4 │ Java面试题71:数据库优化...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...
在未来,我计划继续深入学习Spark和Spring Boot,扩展我的技术栈,提高自己的技能水平。我希望能够运用所学到的知识解决实际问题,并在项目中发挥作用。此外,我也希望能够不断拓宽自己的技术视野,学习其他相关的...