资源描述
Oracle 执行筹划
1,什么是执行筹划
所谓执行筹划,顾名思义,就是对一种查询任务,做出一份如何去完毕任务详细方案。举个生活中例子,我从珠海要去英国,我可以
选取先去香港然后转机,也可以先去北京转机,或者去广州也可以。但是究竟如何去英国划算,也就是我费用至少,这是一件值得考究
事情。同样对于查询而言,咱们提交SQL仅仅是描述出了咱们目地是英国,但至于怎么去,普通咱们SQL中是没有给出提示信息
,是由数据库来决定。
咱们先简朴看一种执行筹划对比:
SQL> set autotrace traceonly
执行筹划一:
SQL> select count(*) from t;
COUNT(*)
----------
24815
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE Access (FULL) OF 'T'
执行筹划二:
SQL> select count(*) from t;
COUNT(*)
24815
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=26 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FULL SCAN) OF 'T_INDEX' (NON-UNIQUE) (Cost=26 Card=28180)
这两个执行筹划中,第一种表达求和是通过进行全表扫描来做,把整个表中数据读入内存来逐条累加;第二个表达依照表中索引,把
整个索引读进内存来逐条累加,而不用去读表中数据。但是这两种方式究竟哪种快呢?普通来说也许二比一快,但也不是绝对。这是一
个很简朴例子演示执行筹划差别。对于复杂SQL(表连接、嵌套子查询等),执行筹划也许几十种甚至上百种,但是究竟那种最佳呢?
咱们事前并不懂得,数据库自身也不懂得,但是数据库会依照一定规则或者记录信息(statistics)去选取一种执行筹划,普通来说选取是
比较优,但也有选取失误时候,这就是这次讨论价值所在。
Oracle优化器模式
Oracle优化器有两大类,基于规则和基于代价,在SQLPLUS中咱们可以查看init文献中定义缺省优化器模式。
SQL> show parameters optimizer_mode
NAME TYPE VALUE
optimizer_mode string CHOOSE
SQL>
这是Oracle8.1.7 公司版,咱们可以看出,默认安装后数据库优化器模式为CHOOSE,咱们还可以设立为 RULE、
FIRST_ROWS,ALL_ROWS。可以在init文献中对整个instance所有会话设立,也可以单独对某个会话设立:
SQL> ALTER SESSION SET optimizer_mode = RULE;
会话已更改。
SQL> ALTER SESSION SET optimizer_mode = FIRST_ROWS;
会话已更改。
SQL> ALTER SESSION SET optimizer_mode = ALL_ROWS;
会话已更改。
基于规则查询,数据库依照表和索引等定义信息,按照一定规则来产生执行筹划;基于代价查询,数据库依照收集表和索引
数据记录信息(通过analyze 命令或者使用dbms_stats包来收集)综合来决定选用一种数据库以为最优执行筹划(事实上不一定最优)。
RULE是基于规则,CHOOSE表达如果查询表存在收集记录信息则基于代价来执行(在CHOOSE模式下Oracle采用是 FIRST_ROWS)
,否则基于规则来执行。在基于代价两种方式中,FIRST_ROWS指执行筹划采用至少资源尽快返回某些成果给客户端,对于排序分页
页显示这种查询特别合用,ALL_ROWS指以总体消耗资源至少方式返回成果给客户端。
基于规则模式下,数据库执行筹划普通比较稳定。但在基于代价模式下,咱们才有更大机会选取最优执行筹划。也由于
Oracle诸多查询方面特性必要在基于代价模式下才干体现出来,因此咱们普通不选取RULE(并且Oracle宣称从 Oracle 10i版本数据库
开始将不再支持 RULE)。既然是基于代价模式,也就是说执行筹划选取是依照表、索引等定义和数据记录信息来决定,这个记录
信息是依照 analyze 命令或者dbms_stats包来定期收集。一方面存在着一种也许,就是由于收集信息是一种很消耗资源和时间动作,尤
其当表数据量很大时候,由于收集信息是对整个表数据进行重新完全记录,因此这是咱们必要慎重考虑问题。咱们只能在服务器空
闲时候定期进行信息收集。这阐明咱们在一段时期内,记录信息也许和数据库自身数据并不吻合;此外就是Oracle记录数据自身也
存在着不精准某些(详细参照Oracle DOCUMENT),更重要一种问题就是及时记录数据相对已经比较精确,但是Oracle优化器选取也
并不是始终是最优方案。这也倚赖于Oracle对不同执行筹划代价计算规则(咱们普通是无法懂得详细计算规则)。这好比咱们决定
从香港还是从北京去英国,车票、机票等实际价格究竟是怎么核算出来咱们并不懂得,或者说咱们当前理解价格信息,在咱们乘车前
往时候,真实价格跟咱们预算已经发生了变化。所有因素,都将影响咱们整个开销。
执行筹划稳定性能带给咱们什么
Oracle存在着执行筹划选取失误也许。这也是咱们经常碰见某些现象,例如总有人说我程序在测试数据库中跑较好,但在产
品数据库上就是跑很差,甚至后者硬件条件比前者还好,这究竟是为什么?硬件资源、记录信息、参数设立都也许对执行筹划产生影响。
由于因素太多,咱们总是对将来怀着一种莫名恐惊,我产品数据库上线后究竟跑好不好?于是Oracle提供了一种稳定执行筹划能力
,也就是把在测试环境中运营良好执行筹划所产生OUTLINES移植到产品数据库,使得执行筹划不会随着其她因素变化而变化。
那么OUTLINES是什么呢?先要简介一种内容,Oracle提供了在SQL中使用HINTS来引导优化器产生咱们想要执行筹划能力。这在
多表连接、复杂查询中特别有效。HINTS类型诸多,可以设立优化器目的(RULE、CHOOSE、FIRST_ROWS、ALL_ROWS),可以指定表
连接顺序,可以指定使用哪个表哪个索引等等,可以对SQL进行诸多精细控制。通过这种方式产生咱们想要执行筹划这些
HINTS,Oracle可以存储这些HINTS,咱们称之为OUTLINES。通过STORE OUTLINES可以使得咱们拥有后来产生相似执行筹划能力,也
就是使咱们拥有了稳定执行筹划能力。
这里想给出一种附加阐明就是,事实上,咱们通过工具改写SQL,例如使用SQL EXPERT改写后SQL,这些不但仅是加了HINTS
并且文本都已经发生了变化SQL,也可以存储OUTLINES,并可被应用到应用中。但这不是一定生效,咱们必要测试检查与否生效。但由
于就算给了错误OUTLINES,数据库在执行时候,也只是忽视过去重新生成执行筹划而不会返回错误,因此咱们才敢放心这样使用。
固然在Oracle文档中并没有指明可以这样做,文档中只是阐明,如果存在OUTLINES同步又在SQL中加了HINTS,则会使用OUTLINES而
忽视HINTS。这个功能在LECCO将发布产品中会使用这一功能,这样可以将SQL EXPERT改写SQL能力和稳定执行筹划能力结合起
来,那么咱们就对不能更改源代码应用品有了相称强大SQL优化能力。
也许咱们会有疑问,如果稳定了执行筹划,那还收集记录信息干吗?这是由于几种因素导致,一方面,当前执行筹划对于将来发生了
变化数据未必就是适当,存在着当前执行筹划不满足将来数据变化后效率,而新记录信息状况下所产生执行筹划也并不
是所有都合理。那这个时候,咱们可以采用新收集记录信息,但是却对新记录信息下不良执行筹划采用Oracle提供执行筹划稳定
性这个能力固定执行筹划,这样结合起来咱们可以建立满意高效数据库运营环境。
咱们还需要关注一种东西,Oracle提供dbms_stats包除了具备收集记录信息能力,还具备把数据库中记录信息(statistics)
export/import能力,还具备只收集记录信息而使得记录信息不应用于数据库能力(把记录信息收集到一种特定表中而不是及时生效)
,在这个基本上咱们就可以把记录信息export出来再import到一种测试环境中,再运营咱们应用,在测试环境中咱们观测最新记录信
息会导致哪些执行筹划发生变化(DB EXPERTPlan Version Tracer是模仿不同环境并自动检查不同环境中执行筹划变化工具),是变好了
还是变差了。咱们可以把变差这一某些在测试环境中使用hints或者运用工具(SQL EXPERT是在重写SQL这一领域当前最强有力工具)产
生良好执行筹划SQL,运用这些SQL可以产生OUTLINES,然后在产品数据库应用最新记录信息同步移植进这些OUTLINES。
最后说一下咱们不得不使用执行筹划稳定性能力场合。咱们假定Oracle优化器选取都是精确,但是优化器选取基本就是我
们SQL,这些SQL才从主线上决定了运营效率,这是更重要一种优化环节。SQL是基本(固然数据库设计是基本基本),一种SQL写
好不好,就相称于咱们同样是要想去英国,但是我起点在珠海,你起点却在西藏最边沿偏僻一种地方,那不论你做如何最优
路线选取,你都不如我在珠海去英国所耗费代价小。
2,怎么生成
1.Explain plan
explain plan for
select * from aa;
查当作果:
select * from table(dbms_xplan.display());
2.Autotrace Set timing on --记录所用时间
Set autot trace --自动记录执行筹划
3.SQL_TRACE
ORACLE SQL_TRACE
“SQL TRACE”是Oracle提供用于进行SQL跟踪手段,是强有力辅助诊断工具。在寻常数据库问题诊断和解决中,“SQL TRACE”是
非常惯用办法。
普通,一次跟踪可以分为如下几步:
1、界定需要跟踪目的范畴,并使用恰当命令启用所需跟踪。
2、通过一段时间后,停止跟踪。此时应当产生了一种跟踪成果文献。
3、找到跟踪文献,并对其进行格式化,然后阅读或分析。
本文就“SQL TRACE”这些使用作简朴探讨,并通过详细案例对SQL_TRACE使用进行阐明。
3,怎么查看执行筹划
从Oracle10g开始,可以通过EXPLAIN PLAN FOR查看DDL语句执行筹划了。
在9i及此前版本,Oracle只能看到DML执行筹划,但是从10g开始,通过EXPLAIN PLAN FOR方式,已经可以看到DDL语句执行筹划
了。
这对于研究CREATE TABLE AS SELECT、CREATE MATERIALIZED VIEW AS SELECT以及CREATE INDEX,ALTER INDEX REBUILD等语
句有很大协助。
举个简朴例子,Oracle文档上对于索引建立有如下描述:
The optimizer can use an existing index to build another index. This results in a much faster index build.
如果看不到DDL执行筹划,只能依照执行时间长短去猜测Oracle详细执行筹划,但是这种办法没有足够说服力。但是通过DDL执
行筹划,就使得成果一目了然了。
SQL> CREATE TABLE T AS SELECT * FROM DBA_OBJECTS;
表已创立。
SQL> EXPLAIN PLAN FOR
2 CREATE INDEX IND_T_NAME ON T(OBJECT_NAME);
已解释。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan hash value:
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | CREATE INDEX STATEMENT | | 57915 | 3732K| 75 (2)| 00:00:01 |
| 1 | INDEX BUILD NON UNIQUE| IND_T_NAME | | | | |
| 2 | SORT CREATE INDEX | | 57915 | 3732K| | |
| 3 | TABLE ACCESS FULL | T | 57915 | 3732K| 41 (3)| 00:00:01 |
-------------------------------------------------------------------------------------
Note
-----
- estimated index size:5242K bytes
已选取14行。
SQL> CREATE INDEX IND_T_OWNER_NAME ON T(OWNER,OBJECT_NAME);
索引已创立。
SQL> EXPLAIN PLAN FOR
2 CREATE INDEX IND_T_NAME ON T(OBJECT_NAME);
已解释。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------
Plan hash value:
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | CREATE INDEX STATEMENT | | 57915 | 3732K| 75 (2)| 00:00:01 |
| 1 | INDEX BUILD NON UNIQUE| IND_T_NAME | | | | |
| 2 | SORT CREATE INDEX | | 57915 | 3732K| | |
| 3 | INDEX FAST FULL SCAN| IND_T_OWNER_NAME | | | | |
-------------------------------------------------------------------------------------------
Note
-----
- estimated index size:5242K bytes
已选取14行。
SQL> SET AUTOT ON
SQL> CREATE INDEX IND_T_NAME ON T(OBJECT_NAME);
索引已创立。
注意,查看DDL执行筹划需要使用EXPLAIN PLAN FOR,AUTOTRACE对于DDL是无效。
4,如何读懂执行筹划:
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'USER_INFO'
3 2 NESTED LOOPS
4 3 TABLE ACCESS (FULL) OF 'USER_NUM_TABLE'
5 3 INDEX (RANGE SCAN) OF 'PK_USER_INFO' (UNIQUE)
请问以上执行筹划语句是如何看?语句执行顺序是什么?
让咱们来解释一下怎么看吧,左边两列数字,第一列表达这条筹划编号,第二列是这条筹划父筹划编号;如果一条筹划有子筹划,
那么先要执行其子筹划;在这个例子中:从第一条编号为0(SELECT STATEMENT ptimizer=CHOOSE)开始,她有个子筹划1(SORT
(AGGREGATE)),然后1有个子筹划2,2有子筹划3, 3 有子筹划4和5,4是3第一种子筹划,因此先执行4(TABLE ACCESS (FULL)
OF 'USER_NUM_TABLE'),再执行5(INDEX (RANGE SCAN) OF 'PK_USER_INFO' (UNIQUE)),4和5执行完返回到其父筹划3(NESTED
LOOPS),3把4和5取到rows进行nested loops,成果再返回到2,再到1排序,再到0select.
Oracle执行筹划解释
一.有关概念
Rowid概念:rowid是一种伪列,既然是伪列,那么这个列就不是顾客定义,而是系统自己给加上。 对每个表均有一种rowid伪列,但是表中并不物理存储ROWID列值。但是你可以像使用其他列那样使用它,但是不能删除改列,也不能对该列值进行 修改、插入。一旦一行数据插入数据库,则rowid在该行生命周期内是唯一,即虽然该行产生行迁移,行rowid也不会变化。
Recursive SQL概念:有时为了执行顾客发出一种sql语句,Oracle必要执行某些额外语句,咱们将这些额外语句称之为''recursive calls''或''recursive SQL statements''.如当一种DDL语句发出后,ORACLE总是隐含发出某些recursive SQL语句,来修改数据字典信息,以便顾客可以成功执行该DDL语句。当需要数据字典信息没有在共享内存中时,经常会发生Recursive calls,这些Recursive calls会将数据字典信息从硬盘读入内存中。顾客不比关怀这些recursive SQL语句执行状况,在需要时候,ORACLE会自动在内部执行这些语句。固然DML语句与SELECT都也许引起recursive SQL.简朴说,咱们可以将触发器视为recursive SQL.
Row Source(行源):用在查询中,由上一操作返回符合条件行集合,即可以是表所有行数据集合;也可以是表某些行数据集合;也可觉得对上2个row source进行连接操作(如join连接)后得到行数据集合。
Predicate(谓词):一种查询中WHERE限制条件
Driving Table(驱动表):该表又称为外层表(OUTER TABLE)。这个概念用于嵌套与HASH连接中。如果该row source返回较多行数据,则对所有后续操作有负面影响。注意此处虽然翻译为驱动表,但事实上翻译为驱动行源(driving row source)更为确切。普通说来,是应用查询限制条件后,返回较少行源表作为驱动表,因此如果一种大表在WHERE条件有有限制条件(如等值限 制),则该大表作为驱动表也是适当,因此并不是只有较小表可以作为驱动表,对的说法应当为应用查询限制条件后,返回较少行源表作为驱动表。在执行 筹划中,应当为靠上那个row source,背面会给出详细阐明。在咱们背面描述中,普通将该表称为连接操作row source 1.
Probed Table(被探查表):该表又称为内层表(INNER TABLE)。在咱们从驱动表中得到详细一行数据后,在该表中寻找符合连接条件行。因此该表应当为大表(事实上应当为返回较大row source表)且相应列上应当有索引。在咱们背面描述中,普通将该表称为连接操作row source 2.
组合索引(concatenated index):由各种列构成索引,如create index idx_emp on emp(col1, col2, col3, ……),则咱们称idx_emp索引为组合索引。在组合索引中有一种重要概念:引导列(leading column),在上面例子中,col1列为引导列。当咱们进行查询时可以使用“where col1 = ? ”,也可以使用“where col1 = ? and col2 = ?”,这样限制条件都会使用索引,但是“where col2 = ? ”查询就不会使用该索引。因此限制条件中包括先导列时,该限制条件才会使用该组合索引。
可选取性(selectivity):比较一下列中唯一键数量和表中行数,就可以判断该列可选取性。 如果该列“唯一键数量/表中行数”比值越接近1,则该列可选取性越高,该列就越适合创立索引,同样索引可选取性也越高。在可选取性高列上进 行查询时,返回数据就较少,比较适合使用索引查询。
二.oracle访问数据存取办法
1) 全表扫描(Full Table Scans, FTS)
为实现全表扫描,Oracle读取表中所有行,并检查每一行与否满足语句WHERE限制条件一种多块读 操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而不是只读取一种数据块,这极大减 少了I/O总次数,提高了系统吞吐量,因此运用多块读办法可以十分高效地实现全表扫描,并且只有在全表扫描状况下才干使用多块读操作。在这种访问模 式下,每个数据块只被读一次。
使用FTS前提条件:在较大表上不建议使用全表扫描,除非取出数据比较多,超过总量5% —— 10%,或你想使用并行查询功能时。
使用全表扫描例子:
~~~~~~~~~~~~~~~~~~~~~~~~ SQL> explain plan for select * from dual;
Query Plan
-----------------------------------------
SELECT STATEMENT[CHOOSE] Cost=
TABLE ACCESS FULL DUAL
2) 通过ROWID表存取(Table Access by ROWID或rowid lookup)
行ROWID指出了该行所在数据文献、数据块以及行在该块中位置,因此通过ROWID来存取数据可以迅速定位到目的数据上,是Oracle存取单行数据最快办法。
这种存取办法不会用到多块读操作,一次I/O只能读取一种数据块。咱们会经常在执行筹划中看到该存取办法,如通过索引查询数据。
使用ROWID存取办法: SQL> explain plan for select * from dept where rowid = ''AAAAyGAADAAAAATAAF'';
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID DEPT [ANALYZED]
3)索引扫描(Index Scan或index lookup)
咱们先通过index查找到数据相应rowid值(对于非唯一索引也许返回各种rowid值),然后依照rowid直接从表中得到详细数据,这 种查找方式称为索引扫描或索引查找(index lookup)。一种rowid唯一表达一行数据,该行相应数据块是通过一次i/o得到,在此状况下该次i/o只会读取一种数据库块。
在索引中,除了存储每个索引值外,索引还存储具备此值行相应ROWID值。索引扫描可以由2步构成:(1) 扫描索引得到相应rowid值。 (2) 通过找到rowid从表中读出详细数据。每步都是单独一次I/O,但是对于索引,由于经常使用,绝大多数都已经CACHE到内存中,因此第1步 I/O经常是逻辑I/O,即数据可以从内存中得到。但是对于第2步来说,如果表比较大,则其数据不也许全在内存中,因此其I/O很有也许是物理I/O,这 是一种机械操作,相对逻辑I/O来说,是极其费时间。因此如果多大表进行索引扫描,取出数据如果不不大于总量5% —— 10%,使用索引扫描会效率下降诸多。如下列所示:SQL> explain plan for select empno, ename from emp where empno=10;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
但是如果查询数据能全在索引中找到,就可以避免进行第2步操作,避免了不必要I/O,此时虽然通过索引扫描取出数据比较多,效率还是很高
SQL> explain plan for select empno from emp where empno=10;-- 只查询empno列值
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
INDEX UNIQUE SCAN EMP_I1
进一步讲,如果sql语句中对索引列进行排序,由于索引已经预先排序好了,因此在执行筹划中不需要再对索引列进行排序
SQL> explain plan for select empno,ename from emp
where empno > 7876 order by empno;
Query Plan
--------------------------------------------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX RANGE SCAN EMP_I1 [ANALYZED]
从这个例子中可以看到:由于索引是已经排序了,因此将按照索引顺序查询出符合条件行,因而避免了进一步排序操作。
依照索引类型与where限制条件不同,有4种类型索引扫描:
索引唯一扫描(index unique scan)
索引范畴扫描(index range scan)
索引全扫描(index full scan)
索引迅速扫描(index fast full scan)
(1) 索引唯一扫描(index unique scan)
通过唯一索引查找一种数值经常返回单个ROWID.如果存在UNIQUE 或PRIMARY KEY 约束(它保证了语句只存取单行)话,Oracle经常实现唯一性扫描。
使用唯一性约束例子:
SQL> explain plan for
select empno,ename from emp where empno=10;
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
(2) 索引范畴扫描(index range scan)
使用一种索引存取多行数据,在唯一索引上使用索引范畴扫描典型状况下是在谓词(where限制条件)中使用了范畴操作符(如>、<、<>、>=、<=、between)
使用索引范畴扫描例子:
SQL> explain plan for select empno,ename from emp
where empno > 7876 order by empno;
Query Plan
--------------------------------------------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
TABLE ACCESS BY ROWID EMP [ANALYZED]
INDEX RANGE SCAN EMP_I1 [ANALYZED]
在非唯一索引上,谓词col = 5也许返回多行数据,因此在非唯一索引上都使用索引范畴扫描。
使用index rang scan3种状况:
(a) 在唯一索引列上使用了range操作符(> < <> >= <= between)
(b) 在组合索引上,只使用某些列进行查询,导致查询出多行
(c) 对非唯一索引列上进行任何查询。
(3) 索引全扫描(index full scan)
与全表扫描相应,也有相应全索引扫描。并且此时查询出数据都必要从索引中可以直接得到。
全索引扫描例子:
An Index full scan will not perform single block i/o''s and so it may prove to be inefficient.
e.g.
Index BE_IX is a concatenated index on big_emp (empno, ename)
SQL> explain plan for select empno, ename from big_emp order by empno,ename;
Query Plan
--------------------------------------------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=26
INDEX FULL SCAN BE_IX [ANALYZED]
(4) 索引迅速扫描(index fast full scan)
扫描索引中所有数据块,与 index full scan很类似,但是一种明显区别就是它不对查询出数据进行排序,即数据不是以排序顺序被返回。在这种存取办法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。
索引迅速扫描例子:
BE_IX索引是一种多列索引: big_emp (empno,ename)
SQL> explain plan for select empno,ename from big_emp;
Query Plan
------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
INDEX FAST FULL SCAN BE_IX [ANALYZED]
只选取多列索引第2列:
SQL> explain plan for select ename from big_emp;
Query Plan
------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
INDEX FAST FULL SCAN BE_IX [ANALYZED]
三、表之间连接
Join是一种试图将两个表结合在一起谓词,一次只能连接2个表,表连接也可以被称为表关联。在背面叙 述中,咱们将会使用“row source”来代替“表”,由于使用row source更严谨某些,并且将参加连接2个row source分别称为row source1和row source 2.Join过程各个环节经常是串行操作,虽然有关row source可以被并行访问,即可以并行读取做join连接两个row source数据,但是在将表中符合限制条件数据读入到内存形成row source后,join其他环节普通是串行。有各种办法可以将2个表连接起来,固然每种办法均有自己优缺陷,每种连接类型只有在特定条件下才会 发挥出其最大优势。
row source(表)之间连接顺序对于查询效率有非常大影响。通过一方面存取特定表,即将该表作为驱动表,这样可以先应用某些限制条件,从而得到一种 较小row source,使连接效率较高,这也就是咱们常说要先执行限制条件因素。普通是在将表读入内存时,应用where子句中对该表限制条件。
依照2个row source连接条件中操作符不同,可以将连接分为等值连接(如WHERE A.COL3 = B.COL4)、非等值连接(WHERE A.COL3 > B.COL4)、外连接(WHERE A.COL3 = B.COL4(+))。上面各个连接连接原理都基本同样,所觉得了简朴期间,下面以等值连接为例进行简介。
在背面简介中,都已:
SELECT A.COL1, B.COL2
FROM A, B
WHERE
展开阅读全文