??xml version="1.0" encoding="utf-8" standalone="yes"?>
OSQ?/span>windows 7 64bit DatabaseQ?/span>mysql-5.7.18-winx64 Noinstall版本
1. 解压Mysql安装目录
2. ~写my.ini配置文g
3. mysqld --defaults-file=../my.ini --initialize
4. ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
5. mysql –u root –p
6. 密码?/span>logs/*.err日志?br />
my.ini文g内容
׃应用pȝ是个软硬件的完整l一体,pȝ调优往往需要涉及硬件?a title="|络" style="color: #000000;" target="_blank">|络?a title="操作pȝ" style="color: #000000;" target="_blank">操作pȝ、中间gQ应用程序和数据库等斚w。在调优的过E中Q往往需要发现存在瓶颈的地方(也就是导致系l变慢的部分)Q分析原因,从而改q和定较优的参数?/p>
我们在作JVM的调优前Q通常先要了解q行的硬件^収ͼ操作pȝ和中间gQ然后针对这些情况配|相应的pȝ参数Q在试中不断完善参数。由于性能调优需要对pȝ非常了解Qƈ且需要丰富的l验Q因此不是一件容易的事情。这里介l一些很好的参考资料,是SPEC.org的网站。这是硬件厂商公布benchmark试l果的地方,通常g厂商会把pȝ调到最优化才公布结果的Q因此很有借鉴意义。常见和JVM有关的benchmarkg要有SPECjAppServer2004和SPECjbb2005。前者是J2EE应用服务器的性能指标Q后者是服务器端Java虚拟机的性能指标。给大家介绍q个|站的目的是说大家可以参考硬件厂商给出的JVM配置Q在Ҏ(gu)自己应用环境的特点,较快的得好的参数。例如,q个|页l出了SUN公司T5120服务?应用服务?.1 +JDK1.5的SPECjAppServer2004值是8,439.36Q?/p>
http://www.spec.org/jAppServer2004/results/res2007q4/jAppServer2004-20071106-00092.html
我们现在要关心的不是Benchmark的?注:实际?Sun公司的这个值是个很不错的结?Q而是留意在这U环境下JVM的参数配|,可以扑ֈ一个栏?#8220;Notes / Tuning Information”Q?/p>
那么上面那些参数是什么意思呢?上述D落?#8220;-XX”的参数是SUN JVM的扩展选项Q其中以下的q些都是和垃圑֛?GC)有关Q?/p>
下面q个选项是选择大的内存面:
-XX:LargePageSizeInBytes=256m
"-XX:+AggressiveOpts"是一些试验性优化参敎ͼ“-XX:-UseBiasedLocking”是非竞争性的同步选项?/p>
而选项“-Xmx2560m -Xms2560m -Xmn1024m -Xss128k”则是初始堆栈的内存|注意-Xmx?Xms的值是一L(fng)Q这L(fng)l性能会较q稳些?/p>
至于q些参数详细代表什么意义,大家可以google一下就很容易了解。这是Sun|站上的说明,有兴的可以M下: http://java.sun.com/performance/reference/whitepapers/tuning.html
如果你的应用pȝ是JDK1.5Q硬件是T5120Q操作系l是SolarisQ那么这些参数就很有借鉴意义。如果你的硬件系l不是T5120Q但是用SUN的JDK1.5 Q这些参C是有一定参考作用。当Ӟ最理想的是选择一个和自己的环境最q似的结果来参考。大多数软硬件的试l果都可以在SPEC.org上找刎ͼ如果你的pȝ是J2EE?层架构,可以用jAppServer2004指标Q如果是UJAVA的应用,可用jbb2005的结?
http://www.spec.org/jAppServer2004/
http://www.spec.org/jbb2005/
需要注意的是,q些调优参数只是提供了一个思\Q具体是否合适你的应用还要看实测l果?/p>
一Q相关的概念
Rowid的概念:rowid是一个伪列,既然是伪列,那么q个列就不是用户定义Q而是pȝ自己l加上的?Ҏ(gu)个表都有一个rowid的伪列,但是表中q不物理存储ROWID列的倹{不q你可以像用其它列那样使用它,但是不能删除改列Q也不能对该列的D?修改、插入。一旦一行数据插入数据库Q则rowid在该行的生命周期内是唯一的,卛_使该行生行q移Q行的rowid也不会改变?/font>
Recursive SQL概念Q有时ؓ了执行用户发出的一个sql语句Q?font color="#0000ff">oracle必须执行一些额外的语句Q我们将q些额外的语句称之ؓ''recursive calls''?'recursive sql statements''.如当一个DDL语句发出后,ORACLEL隐含的发Z些recursive SQL语句Q来修改数据字典信息Q以便用户可以成功的执行该DDL语句。当需要的数据字典信息没有在共享内存中Ӟl常会发生Recursive callsQ这些Recursive calls会将数据字典信息从硬盘读入内存中。用户不比关心这些recursive SQL语句的执行情况,在需要的时候,ORACLE会自动的在内部执行这些语句。当然DML语句与SELECT都可能引起recursive sql.单的_我们可以触发器视ؓrecursive sql.
Row SourceQ行源)Q用在查询中Q由上一操作q回的符合条件的行的集合Q即可以是表的全部行数据的集合;也可以是表的部分行数据的集合Q也可以为对?个row sourceq行q接操作Q如joinq接Q后得到的行数据集合?/p>
PredicateQ谓词)Q一个查询中的WHERE限制条g
Driving tableQ驱动表Q:该表又称为外层表QOUTER tableQ? q个概念用于嵌套与HASHq接中。如果该row sourceq回较多的行数据Q则Ҏ(gu)有的后箋操作有负面媄响。注意此处虽然翻译ؓ驱动表,但实际上译为驱动行源(driving row sourceQ更为确切。一般说来,是应用查询的限制条g后,q回较少行源的表作ؓ驱动表,所以如果一个大表在WHERE条g有有限制条gQ如{值限 ӞQ则该大表作为驱动表也是合适的Q所以ƈ不是只有较小的表可以作ؓ驱动表,正确说法应该为应用查询的限制条g后,q回较少行源的表作ؓ驱动表。在执行 计划中,应该为靠上的那个row sourceQ后面会l出具体说明。在我们后面的描qCQ一般将该表UCؓq接操作的row source 1.
Probed tableQ被探查表)Q该表又UCؓ内层表(INNER tableQ。在我们从驱动表中得到具体一行的数据后,在该表中LW合q接条g的行。所以该表应当ؓ大表Q实际上应该回较大row source的表Q且相应的列上应该有索引。在我们后面的描qCQ一般将该表UCؓq接操作的row source 2.
l合索引Qconcatenated indexQ:由多个列构成的烦引,如create index idx_emp on empQcol1Q?col2Q?col3Q?……Q,则我们称idx_emp索引为组合烦引。在l合索引中有一个重要的概念Q引导列Qleading columnQ,在上面的例子中,col1列ؓ引导列。当我们q行查询时可以?#8220;where col1 = Q?”Q也可以使用“where col1 = Q?and col2 = Q?#8221;Q这L(fng)限制条g都会使用索引Q但?#8220;where col2 = Q? ”查询׃会用该索引。所以限制条件中包含先导列时Q该限制条g才会使用该组合烦引?/p>
可选择性(selectivityQ:比较一下列中唯一键的数量和表中的行数Q就可以判断该列的可选择性? 如果该列?#8220;唯一键的数量/表中的行?#8221;的比D接近1Q则该列的可选择性越高,该列p适合创徏索引Q同L(fng)引的可选择性也高。在可选择性高的列上进 行查询时Q返回的数据p?yu),比较适合使用索引查询?/p>
1Q?全表扫描QFull table ScansQ?FTSQ?/font>
为实现全表扫描,oracle? 取表中所有的行,q检查每一行是否满句的WHERE限制条g一个多块读 操作可以使一ơI/O能读取多块数据块Qdb_block_multiblock_read_count参数讑֮Q,而不是只d一个数据块Q这极大的减 了I/OL敎ͼ提高了系l的吞吐量,所以利用多块读的方法可以十分高效地实现全表扫描Q而且只有在全表扫描的情况下才能用多块读操作。在q种讉K? 式下Q每个数据块只被Mơ?/font>
使用FTS的前提条Ӟ在较大的表上不徏议用全表扫描,除非取出数据的比较多Q超q总量?% —?10%Q或你想使用q行查询功能时?/font>
使用全表扫描的例子:
~~~~~~~~~~~~~~~~~~~~~~~~ sql> explain plan for select * from dual;
Query Plan
-----------------------------------------
SELECT STATEMENT[CHOOSE] Cost=
table ACCESS FULL DUAL
2Q?通过ROWID的表存取QTable Access by ROWID或rowid lookupQ?/font>
行的ROWID指出了该行所在的数据文g、数据块以及行在该块中的位置Q所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法?/font>
q种存取Ҏ(gu)不会用到多块L作,一ơI/O只能d一个数据块。我们会l常在执行计划中看到该存取方法,如通过索引查询数据?/font>
使用ROWID存取的方法: sql> explain plan for select * from dept where rowid = ''AAAAyGAADAAAAATAAF''Q?/font>
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
table ACCESS BY ROWID DEPT [ANALYZED]
3Q烦引扫描(Index Scan或index lookupQ?/p>
我们先通过index查找到数据对应的rowid|对于非唯一索引可能q回多个rowid|Q然后根据rowid直接从表中得到具体的数据Q这 U查找方式称为烦引扫描或索引查找Qindex lookupQ。一个rowid唯一的表CZ行数据,该行对应的数据块是通过一ơi/o得到的,在此情况下该ơi/o只会d一个数据库块?/p>
在烦引中Q除?font color="#0000ff" face="宋体">存储
每个索引的值外Q烦引还存储h此? 的行对应的ROWID倹{烦引扫描可以由2步组成:Q?Q?扫描索引得到对应的rowid倹{?Q?Q? 通过扑ֈ的rowid从表中读出具体的数据。每步都是单独的一ơI/OQ但是对于烦引,׃l常使用Q绝大多数都已经CACHE到内存中Q所以第1步的 I/Ol常是逻辑I/OQ即数据可以从内存中得到。但是对于第2步来_如果表比较大Q则其数据不可能全在内存中,所以其I/O很有可能是物理I/OQ这 是一个机械操作,相对逻辑I/O来说Q是极其Ҏ(gu)间的。所以如果多大表q行索引扫描Q取出的数据如果大于总量?% —? 10%Q用烦引扫描会效率下降很多。如下列所C:SQL> explain plan for select empnoQ?ename from emp where empno=10Q?/p>Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
table ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
但是如果查询的数据能全在索引中找刎ͼ可以避免进行第2步操作,避免了不必要的I/OQ此时即佉K过索引扫描取出的数据比较多Q效率还是很高的
sql> explain plan for select empno from emp where empno=10;-- 只查询empno列?/p>
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
INDEX UNIQUE SCAN EMP_I1
q一步讲Q如果sql语句中对索引列进行排序,因ؓ索引已经预先排序好了Q所以在执行计划中不需要再对烦引列q行排序
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]
从这个例子中可以看到Q因为烦引是已经排序了的Q所以将按照索引的顺序查询出W合条g的行Q因此避免了q一步排序操作?/p>
Ҏ(gu)索引的类型与where限制条g的不同,?U类型的索引扫描Q?/p>
索引唯一扫描Qindex unique scanQ?/p>
索引范围扫描Qindex range scanQ?/p>
索引全扫描(index full scanQ?/p>
索引快速扫描(index fast full scanQ?/p>
Q?Q?索引唯一扫描Qindex unique scanQ?/p>
通过唯一索引查找一个数值经常返回单个ROWID.如果存在UNIQUE 或PRIMARY KEY U束Q它保证了语句只存取单行Q的话,Oraclel常实现唯一性扫描?/p>
使用唯一性约束的例子Q?/p>
sql> explain plan for
select empnoQename from emp where empno=10Q?/p>
Query Plan
------------------------------------
SELECT STATEMENT [CHOOSE] Cost=1
table ACCESS BY ROWID EMP [ANALYZED]
INDEX UNIQUE SCAN EMP_I1
Q?Q?索引范围扫描Qindex range scanQ?/p>
使用一个烦引存取多行数据,在唯一索引上用烦引范围扫描的典型情况下是在谓词(where限制条gQ中使用了范围操作符Q如>?lt;?lt;>?gt;=?lt;=、betweenQ?/p>
使用索引范围扫描的例子:
sql> explain plan for select empnoQename from emp
where empno > 7876 order by empnoQ?/p>
Query Plan
--------------------------------------------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
table ACCESS BY ROWID EMP [ANALYZED]
INDEX RANGE SCAN EMP_I1 [ANALYZED]
在非唯一索引上,谓词col = 5可能q回多行数据Q所以在非唯一索引上都使用索引范围扫描?/p>
使用index rang scan?U情况:
QaQ?在唯一索引列上使用了range操作W(> < <> >= <= betweenQ?/p>
QbQ?在组合烦引上Q只使用部分列进行查询,D查询出多?/p>
QcQ?寚w唯一索引列上q行的Q何查询?/p>
Q?Q?索引全扫描(index full scanQ?/p>
与全表扫描对应,也有相应的全索引扫描。而且此时查询出的数据都必M索引中可以直接得到?/p>
全烦引扫描的例子Q?/p>
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 QempnoQ?enameQ?/p>
sql> explain plan for select empnoQ?ename from big_emp order by empnoQenameQ?/p>
Query Plan
--------------------------------------------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=26
INDEX FULL SCAN BE_IX [ANALYZED]
Q?Q?索引快速扫描(index fast full scanQ?/p>
扫描索引中的所有的数据块,?index full scan很类|但是一个显著的区别是它不Ҏ(gu)询出的数据进行排序,x据不是以排序序被返回。在q种存取Ҏ(gu)中,可以使用多块d能,也可以用ƈ行读入,以便获得最大吞吐量与羃短执行时间?/p>
索引快速扫描的例子Q?/p>
BE_IX索引是一个多列烦引: big_emp QempnoQenameQ?/p>
sql> explain plan for select empnoQename from big_empQ?/p>
Query Plan
------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
INDEX FAST FULL SCAN BE_IX [ANALYZED]
只选择多列索引的第2列:
sql> explain plan for select ename from big_empQ?/p>
Query Plan
------------------------------------------
SELECT STATEMENT[CHOOSE] Cost=1
INDEX FAST FULL SCAN BE_IX [ANALYZED]
三、表之间的连?/strong>
Join是一U试囑ְ两个表结合在一L(fng)谓词Q一ơ只能连?个表Q表q接也可以被UCؓ表关联。在后面的叙 qCQ我们将会?#8220;row source”来代?#8220;?#8221;Q因Z用row source更严谨一些,q且参与连接的2个row source分别UCؓrow source1和row source 2.Joinq程的各个步骤经常是串行操作Q即使相关的row source可以被ƈ行访问,卛_以ƈ行的d做joinq接的两个row source的数据,但是在将表中W合限制条g的数据读入到内存形成row source后,join的其它步骤一般是串行的。有多种Ҏ(gu)可以?个表q接hQ当然每U方法都有自q优缺点,每种q接cd只有在特定的条g下才? 发挥出其最大优ѝ?/font>
row sourceQ表Q之间的q接序对于查询的效率有非常大的影响。通过首先存取特定的表Q即该表作为驱动表Q这样可以先应用某些限制条gQ从而得C? 较小的row sourceQɘq接的效率较高,q也是我们常说的要先执行限制条件的原因。一般是在将表读入内存时Q应用where子句中对该表的限制条件?/font>
Ҏ(gu)2个row source的连接条件的中操作符的不同,可以连接分为等D接(如WHERE A.COL3 = B.COL4Q、非{D接(WHERE A.COL3 > B.COL4Q、外q接QWHERE A.COL3 = B.COL4Q?Q)。上面的各个q接的连接原理都基本一P所以ؓ了简单期_下面以等D接ؓ例进行介l?/font>
在后面的介绍中,都已Q?/font>
SELECT A.COL1Q?B.COL2
FROM AQ?B
WHERE A.COL3 = B.COL4Q?/font>
Zq行说明Q假设A表ؓRow Soruce1Q则其对应的q接操作兌列ؓCOL 3QB表ؓRow Soruce2Q则其对应的q接操作兌列ؓCOL 4Q?/font>
q接cdQ?/font>
目前为止Q无接操作符如何Q典型的q接cd共有3U:
排序 - - 合ƈq接QSort Merge Join QSMJQ?Q?/font>
嵌套循环QNested Loops QNLQ?Q?/font>
哈希q接QHash JoinQ?/font>
排序 - - 合ƈq接QSort Merge JoinQ?SMJQ?/font>
内部q接q程Q?/font>
1Q?首先生成row source1需要的数据Q然后对q些数据按照q接操作兌列(如A.col3Q进行排序?/font>
2Q?随后生成row source2需要的数据Q然后对q些数据按照与sort source1对应的连接操作关联列Q如B.col4Q进行排序?/font>
3Q?最后两边已排序的行被放在一h行合q操作,卛_2个row source按照q接条gq接h
下面是连接步骤的囑Ş表示Q?/font>
MERGE
/"
SORTSORT
||
Row Source 1Row Source 2
如果row source已经在连接关联列上被排序Q则该连接操作就不需要再q行sort操作Q这样可以大大提高这U连接操作的q接速度Q因为排序是个极其费资源的操 作,特别是对于较大的表。预先排序的row source包括已经被烦引的列(如a.col3或b.col4上有索引Q或row source已经在前面的步骤中被排序了。尽合q两个row source的过E是串行的,但是可以q行讉Kq两个row sourceQ如q行d数据Qƈ行排序)?/font>
SMJq接的例子:SQL> explain plan for
select /*+ ordered */ e.deptnoQ?d.deptno
from emp eQ?dept d
where e.deptno = d.deptno
order by e.deptnoQ?d.deptnoQ?/font>
Query Plan
-------------------------------------
SELECT STATEMENT [CHOOSE] Cost=17
MERGE JOIN
SORT JOIN
table ACCESS FULL EMP [ANALYZED]
SORT JOIN
table ACCESS FULL DEPT [ANALYZED]
排序是一个费时、费资源的操作,特别对于大表。基于这个原因,SMJl常不是一个特别有效的q接Ҏ(gu)Q但是如?个row source都已l预先排序,则这U连接方法的效率也是蛮高的?/p>
嵌套循环QNested LoopsQ?NLQ?/strong>
q个q接Ҏ(gu)有驱动表Q外部表Q的概念。其实,该连接过E就是一?层嵌套@环,所以外层@环的ơ数少好Q这也就是我们ؓ什么将表或返回较?yu)? row source的表作ؓ驱动表(用于外层循环Q的理论依据。但是这个理论只是一般指导原则,因ؓ遵@q个理论q不能M证语句产生的I/Oơ数最。有? 不遵守这个理Z据,反而会获得更好的效率。如果用这U方法,军_使用哪个表作为驱动表很重要。有时如果驱动表选择不正,会D语句的性能很差、很 差?/p>
内部q接q程Q?/p>
Row source1的Row 1 —?Probe ->Row source 2
Row source1的Row 2 —?Probe ->Row source 2
Row source1的Row 3 —?Probe ->Row source 2
……?/p>
Row source1的Row n —?Probe ->Row source 2
从内部连接过E来看,需要用row source1中的每一行,d配row source2中的所有行Q所以此时保持row source1可能的与高效的访问row source2Q一般通过索引实现Q是影响q个q接效率的关键问题。这只是理论指导原则Q目的是使整个连接操作生最的物理I/Oơ数Q而且如果遵守q? 个原则,一般也会ȝ物理I/O数最。但是如果不遵从q个指导原则Q反而能用更的物理I/O实现q接操作Q那管q反指导原则吧!因ؓ最的物理 I/Oơ数才是我们应该遵从的真正的指导原则Q在后面的具体案例分析中qL(fng)例子?/p>
在上面的q接q程中,我们URow source1为驱动表或外部表。Row Source2被称探查表或内部表?/p>
在NESTED LOOPSq接中,Oracledrow source1中的每一行,然后在row sourc2中检查是否有匚w的行Q所有被匚w的行都被攑ֈl果集中Q然后处理row source1中的下一行。这个过E一直l,直到row source1中的所有行都被处理。这是从q接操作中可以得到第一个匹配行的最快的Ҏ(gu)之一Q这U类型的q接可以用在需要快速响应的语句中,以响应速度? 主要目标?/p>
如果driving row sourceQ外部表Q比较小Qƈ且在inner row sourceQ内部表Q上有唯一索引Q或有高选择性非唯一索引Ӟ使用q种Ҏ(gu)可以得到较好的效率。NESTED LOOPS有其它连接方法没有的的一个优Ҏ(gu)Q可以先q回已经q接的行Q而不必等待所有的q接操作处理完才q回数据Q这可以实现快速的响应旉?/p>
如果不用ƈ行操作,最好的驱动表是那些应用了where 限制条g后,可以q回较少行数据的的表Q所以大表也可能UCؓ驱动表,关键看限制条件。对于ƈ行查询,我们l常选择大表作ؓ驱动表,因ؓ大表可以充分利用q? 行功能。当Ӟ有时Ҏ(gu)询用ƈ行操作ƈ不一定会比查询不使用q行操作效率高,因ؓ最后可能每个表只有很少的行W合限制条gQ而且q要看你的硬仉|是? 可以支持q行Q如是否有多个CPUQ多个硬盘控制器Q,所以要具体问题具体对待?/p>
NLq接的例子:
sql> explain plan for
select a.dnameQb.sql
from dept aQemp b
where a.deptno = b.deptnoQ?/p>
Query Plan
-------------------------
SELECT STATEMENT [CHOOSE] Cost=5
NESTED LOOPS
table ACCESS FULL DEPT [ANALYZED]
table ACCESS FULL EMP [ANALYZED]
哈希q接QHash JoinQ?HJQ?/strong>
q种q接是在oracle 7.3以后引入的,从理Z来说比NL与SMJ更高效,而且只用在CBO优化器中?/p>
较小的row source被用来构建hash table与bitmapQ第2个row source被用来被hansedQƈ与第一个row source生成的hash tableq行匚wQ以便进行进一步的q接。Bitmap被用来作ZU比较快的查找方法,来检查在hash table中是否有匚w的行。特别的Q当hash table比较大而不能全部容U_内存中时Q这U查找方法更为有用。这U连接方法也有NLq接中所谓的驱动表的概念Q被构徏为hash table与bitmap的表为驱动表Q当被构建的hash table与bitmap能被容纳在内存中Ӟq种q接方式的效率极高?/p>
HASHq接的例子:
sql> explain plan for
select /*+ use_hashQempQ?*/ empno
from empQ?dept
where emp.deptno = dept.deptnoQ?/p>
Query Plan
----------------------------
SELECT STATEMENT[CHOOSE] Cost=3
HASH JOIN
table ACCESS FULL DEPT
table ACCESS FULL EMP
要哈希q接有效Q需要设|HASH_JOIN_ENABLED=TRUEQ缺省情况下该参CؓTRUEQ另外,不要忘了q要讄
hash_area_size参数Q以使哈希连接高效运行,因ؓ哈希q接会在该参数指定大的内存中运行,q小的参C使哈希连接的性能比其他连接方式还
要低?/p>
ȝ一下,在哪U情况下用哪U连接方法比较好Q?/p>
排序 - - 合ƈq接QSort Merge JoinQ?SMJQ:
aQ?对于非等D接,q种q接方式的效率是比较高的?/p>
bQ?如果在关联的列上都有索引Q效果更好?/p>
cQ?对于?个较大的row source做连接,该连接方法比NLq接要好一些?/p>
dQ?但是如果sort mergeq回的row sourceq大Q则又会D使用q多的rowid在表中查询数据时Q数据库性能下降Q因多的I/O.
嵌套循环QNested LoopsQ?NLQ:
aQ?如果driving row sourceQ外部表Q比较小Qƈ且在inner row sourceQ内部表Q上有唯一索引Q或有高选择性非唯一索引Ӟ使用q种Ҏ(gu)可以得到较好的效率?/p>
bQ?NESTED LOOPS有其它连接方法没有的的一个优Ҏ(gu)Q可以先q回已经q接的行Q而不必等待所有的q接操作处理完才q回数据Q这可以实现快速的响应旉?/p>
哈希q接QHash JoinQ?HJQ:
aQ?q种Ҏ(gu)是在oracle7后来引入的,使用了比较先q的q接理论Q一般来_其效率应该好于其?U连接,但是q种q接只能用在CBO优化器中Q而且需要设|合适的hash_area_size参数Q才能取得较好的性能?/p>
bQ??个较大的row source之间q接时会取得相对较好的效率,在一个row source较小时则能取得更好的效率?/p>
cQ?只能用于{D接中
W卡儿乘U(Cartesian ProductQ?/p>
当两个row source做连接,但是它们之间没有兌条gӞ׃在两个row source中做W卡儿乘U,q通常q写代码疏漏造成Q即E序员忘了写兌条gQ。笛卡尔乘积是一个表的每一行依ơ与另一个表中的所有行匚w。在Ҏ(gu)? 况下我们可以使用W卡儿乘U,如在星Şq接中,除此之外Q我们要量使用W卡儿乘U,否则Q自己想l果是什么吧Q?/p>
注意在下面的语句中,?个表之间没有q接?/p>
sql> explain plan for
select emp.deptnoQdeptQdeptno
from empQdept
Query Plan
------------------------
SLECT STATEMENT [CHOOSE] Cost=5
MERGE JOIN CARTESIAN
table ACCESS FULL DEPT
SORT JOIN
table ACCESS FULL EMP
CARTESIAN关键字指Z?个表之间做笛卡尔乘积。假如表emp有n行,dept表有m行,W卡乘U的l果是得到n * m行结果?/p>