Oracle性能优化David~Chen

ORACLE将执行过的SQL语句存放在内存的共享池(sharedbufferpool)中,可以被所有的数据库用户共享。当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径.这个功能大大地提高了SQL的执行性能并节省了内存的使用。

为了不重复解析相同的SQL语句,在第一次解析之后,Oracle将SQL语句存放在内存中。这块位于系统全局区域SGA(systemglobalarea)的共享池(sharedbufferpoo1)中的内存可以被所有的数据库用户共享。因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前执行过的语句完全相同,Oracle就能很快获得已经被解析的语句以及最好的执行方案。Oracle的这个功能大大地提高了SQL的执行性能并节省了内存的使用。

可惜的是,Oracle只对简单的表提供高速缓冲(cachebufferiIlg),这个功能并不适用于多表连接查询。数据库管理员必须在启动参数文件中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了。当向Oracle提交一个SQL语句时,Oracle会首先在这块内存中查找相同的语句。

要使用内存中共享池的SQL,必须满足以下条件:当前被执行的语句和共享池中的语句必须完全相同(包括大小写、空格、换行等),两个语句所指的对象必须完全相同(同义词与表是不同的对象)两个SQL语句中必须使用相同的名字的绑定变量(bindvariables)。Oracle对两者采取的是一种严格匹配策略,要达成共享。SQL语句必须完全相同(包括空格、换行等)。

能够使用共享的语句必须满足三个条件:①字符级的比较。当前被执行的语句和共享池中的语句必须完全相同。例如:SELECT*FROMATABLE;和下面每一个SQL语句都不同:SELECT*fromATABLE;Select*FromAtable;②语句所指对象必须完全相同即两条SQL语句操作的数据库对象必须同一。③语句中必须使用相同命名的绑定变量。如:第一组的两个SQL语句是相同的,可以共享;而第二组中两个语句不同,即使在运行时赋予不同的绑定变量以相同的值:●第一组selectpin,namefrompeoplewherepin=:blk1.pin;selectpin,namefrompeoplewherepin=:blk1.pin;●第二组selectpin,namefrompeoplewherepin=:blk1.ot_jnd;selectpin,namefrompeoplewherepin=:blk1.ov_jnd;

为什么要绑定变量?

下面这个语句每执行一次就需要在SHAREPOOL硬解析一次,一百万用户就是一百万次,消耗CPU和内存,如果业务量大,很可能导致宕库……如果绑定变量,则只需要硬解析一次,重复调用即可。select*fromdConMsgwherecontract_no=32013484095139

硬解析即整个SQL语句的执行需要完完全全的解析,生成执行计划。而硬解析,生成执行计划需要耗用CPU资源,以及SGA资源。在此不得不提的是对库缓存中闩的使用。闩是锁的细化,可以理解为是一种轻量级的串行化设备。当进程申请到闩后,则这些闩用于保护共享内存的数在同一时刻不会被两个以上的进程修改。在硬解析时,需要申请闩的使用,而闩的数量在有限的情况下需要等待。大量的闩的使用由此造成需要使用闩的进程排队越频繁,性能则逾低下。

绑定变量解决硬解析问题

未使用绑定变量的语句sprintf(sqlstr,"insertintoscott.test1(num1,num2)values(%d,%d)",n_var1,n_var2);EXECSQLEXECUTEIMMEDIATE:sqlstr;EXECSQLCOMMIT;使用绑定变量的语句strcpy(sqlstr,"insertintotest(num1,num2)values(:v1,:v2)");EXECSQLPREPAREsql_stmtFROM:sqlstr;EXECSQLEXECUTEsql_stmtUSING:n_var1,:n_var2;EXECSQLCOMMIT;

SQL优化

目标:

设计方面:

编码方面:

随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于大量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来使用索引,这有助于写出高性能的SQL语句。SQL语句的编写原则和SQL语句的优化,请跟我一起学习以下几方面:

fromuser_filesuf,df_money_filesdm,

cw_charge_recordcc

where

uf.user_no=dm.user_no

anddm.user_no=cc.user_no

and……

andnotexists(select…)

很难优化,随着数据量的增加性能的风险很大。

通常,带有UNION,MINUS,INTERSECT的SQL语句都可以用其他方式重写。

低效:

SELECTDISTINCTDEPT_NO,DEPT_NAME

FROMDEPTD,EMPE

WHERED.DEPT_NO=E.DEPT_NO

高效:

SELECTDEPT_NO,DEPT_NAME

FROMDEPTD

WHEREEXISTS(SELECT‘X’

FROMEMPE

WHEREE.DEPT_NO=D.DEPT_NO);

举例:

低效:

SELECTACCT_NUM,BALANCE_AMT

FROMDEBIT_TRANSACTIONS

WHERETRAN_DATE=’31-DEC-95’

UNION

UNIONALL

SELECTENAME

FROMEMP

WHEREEMPNO=2326

ANDDEPTNO=20;

这里,只有EMPNO上的索引是唯一性的,所以EMPNO索引将用来检索记录.

TABLEACCESSBYROWIDONEMP

INDEXUNIQUESCANONEMP_NO_IDX

如果索引是建立在多个列上,只有在它的第一个列(leadingcolumn)被where子句引用时,优化器才会选择使用该索引。

SQL>createtablemultiindexusage(indanumber,indbnumber,descrvarchar2(10));

Tablecreated.

SQL>createindexmultindexonmultiindexusage(inda,indb);

Indexcreated.

SQL>setautotracetraceonly

SQL>select*frommultiindexusagewhereinda=1;

ExecutionPlan

----------------------------------------------------------

0SELECTSTATEMENTOptimizer=CHOOSE

10TABLEACCESS(BYINDEXROWID)OF'MULTIINDEXUSAGE'

21INDEX(RANGESCAN)OF'MULTINDEX'(NON-UNIQUE)

SQL>select*frommultiindexusagewhereindb=1;

10TABLEACCESS(FULL)OF'MULTIINDEXUSAGE'

很明显,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引。

WHERE子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描。

SELECT…

FROMDEPT

WHERESAL*12>25000;

WHERESAL>25000/12;

WHERE子句中,如果索引列所对应的值的第一个字符由通配符(WILDCARD)开始,索引将不被采用。

SELECTUSER_NO,USER_NAME,ADDRESS

FROMUSER_FILES

WHEREUSER_NOLIKE'%109204421';

在这种情况下,ORACLE将使用全表扫描。

低效:(这里,不使用索引)

WHEREDEPT_CODE<>0;

高效:(这里,使用了索引)

WHEREDEPT_CODE>0;

如果唯一性索引建立在表的A列和B列上,并且表中存在一条记录的A,B值为(123,null),ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入).然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空.因此你可以插入1000条具有相同键值的记录,当然它们都是空!

因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.

任何在where子句中使用isnull或isnotnull的语句优化器是不允许使用索引的。

假设EMP_TYPE是一个字符类型的索引列.

WHEREUSER_NO=109204421

这个语句被ORACLE转换为:

WHERETO_NUMBER(USER_NO)=109204421

因为内部发生的类型转换,这个索引将不会被用到!

SELECTCOUNT(*),SUM(SAL)

WHEREDEPT_NO=0020

ANDENAMELIKE‘SMITH%’;

WHEREDEPT_NO=0030

你可以用DECODE函数高效地得到相同结果

SELECTCOUNT(DECODE(DEPT_NO,0020,’X’,NULL))D0020_COUNT,

COUNT(DECODE(DEPT_NO,0030,’X’,NULL))D0030_COUNT,

SUM(DECODE(DEPT_NO,0020,SAL,NULL))D0020_SAL,

SUM(DECODE(DEPT_NO,0030,SAL,NULL))D0030_SAL

FROMEMPWHEREENAMELIKE‘SMITH%’;

例如:

低效

SELECTTAB_NAME

FROMTABLES

WHERETAB_NAME=(SELECTTAB_NAME

FROMTAB_COLUMNS

WHEREVERSION=604)

ANDDB_VER=(SELECTDB_VER

高效

WHERE(TAB_NAME,DB_VER)

=(SELECTTAB_NAME,DB_VER)

最好不要在WHERE子句中使用函或表达式,如果要使用的话,最好统一使用相同的表达式或函数,这样便于以后使用合理的索引。

ORDERBY语句决定了Oracle如何将返回的查询结果排序。Orderby语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Orderby语句的非索引项或者有计算表达式都将降低查询速度。仔细检查orderby语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写orderby语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在orderby子句中使用表达式。

对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。

select*fromemployss

first_name||''||last_name='BeillCliton';

系统优化器对基于last_name创建的索引没有使用。

当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。

select*fromemployeewherefirst_name='Beill'andlast_name='Cliton';

通配符(%)在搜寻词首出现,Oracle系统不使用last_name的索引。

select*fromemployeewherelast_namelike'%cliton%';

在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:

select*fromemployeewherelast_namelike'c%';

避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。

SELECTREGION,AVG(LOG_SIZE)

FROMLOCATION

GROUPBYREGION

HAVINGREGIONREGION!=‘SYDNEY’

ANDREGION!=‘PERTH’

WHEREREGIONREGION!=‘SYDNEY’

顺序

WHERE>GROUP>HAVING

在子查询中,NOTIN子句将执行一个内部的排序和合并.无论在哪种情况下,NOTIN都是最低效的(因为它对子查询中的表执行了一个全表遍历)。

使用NOTEXISTS子句可以有效地利用索引。尽可能使用NOTEXISTS来代替NOTIN,尽管二者都使用了NOT(不能使用索引而降低速度),NOTEXISTS要比NOTIN查询效率更高。

deptnoNOTIN(SELECTdeptnoFROMemp);

NOTEXISTS

(SELECTdeptnoFROMempWHEREdept.deptno=emp.deptno);

2要比1的执行性能好很多。

索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构.通常,通过索引查询数据比全表扫描要快.当ORACLE找出执行查询和Update语句的最佳路径时,ORACLE优化器将使用索引.同样在联结多个表时使用索引也可以提高效率.另一个使用索引的好处是,它提供了主键(primarykey)的唯一性验证。

WHERE子句中,如果索引列是函数的一部分.优化器将不

使用索引而使用全表扫描.

SELECT…FROMDEPTWHERESAL*12>25000;

SELECT…FROMDEPTWHERESAL>25000/12;

SELECT*

WHEREDEPTNO>=4

WHEREDEPTNO>3

例子:

虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。

外部联接"+"按其在"="的左边或右边分左联接和右联接。若不带"+"运算符的表中的一个行不直接匹配于带"+"预算符的表中的任何行,则前者的行与后者中的一个空行相匹配并被返回。利用外部联接"+",可以替代效率十分低下的notin运算,大大提高运行速度。例如,下面这条命令执行起来很慢:

事务是消耗资源的,大事务还容易引起死锁

COMMIT所释放的资源:

当删除表中的记录时,在通常情况下,回滚段(rollbacksegments)用来存放可以被恢复的信息.如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)

例如COUNT(EMPNO)

比如有的表PHONE_NO字段是CHAR型,而且创建有索引,

但在WHERE条件中忘记了加引号,就不会用到索引。

WHEREPHONE_NO=‘13920202022’

WHEREPHONE_NO=13920202022

SQL语句的处理过程

语法分析分别执行下列操作:

查询与其它类型的SQL语句不同,因为在成功执行后作为结果将返回数据。

第3步:描述查询结果(DescribeResultsofaQuery)

描述阶段只有在查询结果的各个列是未知时才需要;例如,当查询由用户交互地输入需要输出的列名。在这种情况要用描述阶段来决定查询结果的特征(数据类型,长度和名字)。

第4步:定义查询的输出数据(DefineOutputofaQuery)

在查询的定义阶段,你指定与查询出的列值对应的接收变量的位置、大小和数据类型,这样我们通过接收变量就可以得到查询结果。如果必要的话,Oracle会自动实现数据类型的转换。这是将接收变量的类型与对应的列类型相比较决定的。

第5步:绑定变量(BindAnyVariables)

第8步:取出查询的行(FetchRowsofaQuery)

第9步:关闭游标(ClosetheCursor)SQL语句处理的最后一个阶段就是关闭游标。

Oralce优化器

2种类型的优化器:基于规则的优化器基于代价的优化器。

不同之处:取得代价的方法与衡量代价的大小不同。

基于规则的优化器--RuleBased(Heuristic)Optimization(简称RBO)

基于代价的优化器--CostBasedOptimization(简称CBO)

Oracle把一个代价引擎(CostEngine)集成到数据库内核中,用来估计每个执行计划需要的代价,该代价将每个执行计划所耗费的资源进行量化,从而CBO可以根据这个代价选择出最优的执行计划。查询耗费的资源可以被分成3个基本组成部分:I/O代价、CPU代价、network代价。

Oracle执行计划

为了不重复解析相同的SQL语句(因为解析操作比较费资源,会导致性能下降),在第一次解析之后,ORACLE将SQL语句及解析后得到的执行计划存放在内存中。这块位于系统全局区域SGA(systemglobalarea)的共享池(sharedbufferpool)中的内存可以被所有的数据库用户共享。因此,当你执行一个SQL语句(有时被称为一个游标)时,如果该语句和之前的执行过的某一语句完全相同,并且之前执行的该语句与其执行计划仍然在内存中存在,则ORACLE就不需要再进行分析,直接得到该语句的执行路径。ORACLE的这个功能大大地提高了SQL的执行性能并大大节省了内存的使用。使用这个功能的关键是将执行过的语句尽可能放到内存中,所以这要求有大的共享池(通过设置sharedbufferpool参数值)和尽可能的使用绑定变量的方法执行SQL语句。

Rowid的概念

rowid是一个伪列,既然是伪列,那么这个列就不是用户定义,而是系统自己给加上的。对每个表都有一个rowid的伪列,但是表中并不物理存储ROWID列的值。不过你可以像使用其它列那样使用它,但是不能删除该列,也不能对该列的值进行修改、插入。一旦一行数据插入数据库,则rowid在该行的生命周期内是唯一的,即即使该行产生行迁移,行的rowid也不会改变。

为什么使用Rowid

rowid对访问一个表中的给定的行提供了最快的访问方法,通过ROWID可以直接定位到相应的数据块上,然后将其读到内存。我们创建一个索引时,该索引不但存储索引列的值,而且也存储索引值所对应的行的ROWID,这样我们通过索引快速找到相应行的ROWID后,通过该ROWID,就可以迅速将数据查询出来。这也就是我们使用索引查询时,速度比较快的原因。

在ORACLE8以前的版本中,ROWID由FILE、BLOCK、ROWNUMBER构成。随着oracle8中对象概念的扩展,ROWID发生了变化,ROWID由OBJECT、FILE、BLOCK、ROWNUMBER构成。利用DBMS_ROWID可以将rowid分解成上述的各部分,也可以将上述的各部分组成一个有效的rowid。

RowSource(行源)

用在查询中,由上一操作返回的符合条件的行的集合,即可以是表的全部行数据的集合;也可以是表的部分行数据的集合;也可以为对上2个rowsource进行连接操作(如join连接)后得到的行数据集合。

Predicate(谓词)

一个查询中的WHERE限制条件。DrivingTable(驱动表)

该表又称为外层表(OUTERTABLE)。这个概念用于嵌套与HASH连接中。如果该rowsource返回较多的行数据,则对所有的后续操作有负面影响。注意此处虽然翻译为驱动表,但实际上翻译为驱动行源(drivingrowsource)更为确切。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一个大表在WHERE条件有限制条件(如等值限制),则该大表作为驱动表也是合适的,所以并不是只有较小的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行计划中,应该为靠上的那个rowsource,后面会给出具体说明。在我们后面的描述中,一般将该表称为连接操作的rowsource1。

ProbedTable(被探查表)

该表又称为内层表(INNERTABLE)。在我们从驱动表中得到具体一行的数据后,在该表中寻找符合连接条件的行。所以该表应当为大表(实际上应该为返回较大rowsource的表)且相应的列上应该有索引。在我们后面的描述中,一般将该表称为连接操作的rowsource2。

组合索引(concatenatedindex)

由多个列构成的索引,如createindexidx_emponemp(col1,col2,col3,……),则我们称idx_emp索引为组合索引。在组合索引中有一个重要的概念:引导列(leadingcolumn),在上面的例子中,col1列为引导列。当我们进行查询时可以使用”wherecol1=”,也可以使用”wherecol1=andcol2=”,这样的限制条件都会使用索引,但是”wherecol2=”查询就不会使用该索引。所以限制条件中包含先导列时,该限制条件才会使用该组合索引。

可选择性(selectivity)

比较一下列中唯一键的数量和表中的行数,就可以判断该列的可选择性。如果该列的”唯一键的数量/表中的行数”的比值越接近1,则该列的可选择性越高,该列就越适合创建索引,同样索引的可选择性也越高。在可选择性高的列上进行查询时,返回的数据就较少,比较适合使用索引查询。

从而找出影响性能的主要问题。举例,如何得到执行计划:

显示下面SQL语句的执行计划。

¨SELECTename,job,sal,dname

¨FROMemp,dept

1、Oracle实现步骤5,并将结果ROWID返回给第4步。2、Oracle实现步骤4,并将结果行返回给第2步。3、Oracle实现步骤2,将接受来自第3步的一行和来自第4步的一行,并返回给第1步一行。4、Oracle实现步骤6,如果有结果行的话,将它返回给第1步。5、Oracle实现步骤1,如果从步骤6返回行,Oracle将来自第2步的行返回给发出SQL语句的用户。

有时语句执行时,并不是象上面说的那样一步一步有先有后的进行,而是可能并行运行,如在实际环境中,3、5、4步可能并行运行,以便取得更好的效率。从上面的树型图上,是很难看出各个操作执行的先后顺序,而通过ORACLE生成的另一种形式的执行计划,则可以很容易的看出哪个操作先执行,哪个后执行,这样的执行计划是我们真正需要的,后面会给出详细说明。现在先来看一些预备知识。

优化器在形成执行计划时需要做的一个重要选择是如何从数据库查询出需要的数据。对于SQL语句存取的任何表中的任何行,可能存在许多存取路径(存取方法),通过它们可以定位和查询出需要的数据。优化器选择其中自认为是最优化的路径。在物理层,oracle读取数据,一次读取的最小单位为数据库块(由多个连续的操作系统块组成),一次读取的最大值由操作系统一次I/O的最大值与multiblock参数共同决定,所以即使只需要一行数据,也是将该行所在的数据库块读入内存。逻辑上,oracle用如下存取方法访问数据:

通过ROWID的表存取(TableAccessbyROWID或rowidlookup)

行的ROWID指出了该行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。为通过ROWID存取表,Oracle首先要获取被选择行的ROWID,或从语句的WHERE子句中得到,或者通过表的一个或多个索引的索引扫描得到。Oracle然后以得到的ROWID为依据定位每个被选择的行。此存取方法不会用到多块读操作,一次I/O只能读取一个数据块。我们经常在执行计划中看到该存取方法,如通过索引查询数据。使用ROWID存取的方法:

!8431bb36e2fa4647aa490996eeaee021.jpg!如果rowsource已经在连接关联列上被排序,则该连接操作就不需要再进行sort操作,这样可以大大提高这种连接操作的连接速度,因为排序是个极其费资源的操作,特别是对于较大的表。预先排序的rowsource包括已经被索引的列(如a.col3或b.col4上有索引)或rowsource已经在前面的步骤中被排序了。尽管合并两个rowsource的过程是串行的,但是可以并行访问这两个rowsource(如并行读入数据,并行排序).排序是一个费时、费资源的操作,特别对于大表。基于这个原因,SMJ经常不是一个特别有效的连接方法,但是如果2个rowsource都已经预先排序,则这种连接方法的效率较高。

SMJ连接的例子:

SQL>explainplanfor

select/*+ordered*/e.deptno,d.deptno

fromempe,deptd

wheree.deptno=d.deptno

orderbye.deptno,d.deptno;

QueryPlan

-------------------------------------

SELECTSTATEMENT[CHOOSE]Cost=17

MERGEJOIN

SORTJOIN

TABLEACCESSFULLEMP[ANALYZED]

TABLEACCESSFULLDEPT[ANALYZED]

嵌套循环(NestedLoops(NL))

NL连接的例子:

selecta.dname,b.sql

fromdepta,empb

wherea.deptno=b.deptno;

-------------------------

SELECTSTATEMENT[CHOOSE]Cost=5

NESTEDLOOPS

哈希连接(HashJoin,HJ)

理论上来说比NL与SMJ更高效,而且只用在CBO优化器中。较小的rowsource被用来构建hashtable与bitmap,第2个rowsource被用来被hansed,并与第一个rowsource生成的hashtable进行匹配,以便进行进一步的连接。Bitmap被用来作为一种比较快的查找方法,来检查在hashtable中是否有匹配的行。特别的,当hashtable比较大而不能全部容纳在内存中时,这种查找方法更为有用。这种连接方法也有NL连接中所谓的驱动表的概念,被构建为hashtable与bitmap的表为驱动表,当被构建的hashtable与bitmap能被容纳在内存中时,这种连接方式的效率极高。要使哈希连接有效,需要设置HASH_JOIN_ENABLED=TRUE,缺省情况下该参数为TRUE,另外,不要忘了还要设置hash_area_size参数,以使哈希连接高效运行,因为哈希连接会在该参数指定大小的内存中运行,过小的参数会使哈希连接的性能比其他连接方式还要低。

HASH连接的例子:

select/*+use_hash(emp)*/empno

fromemp,dept

whereemp.deptno=dept.deptno;

----------------------------

SELECTSTATEMENT[CHOOSE]Cost=3

HASHJOIN

TABLEACCESSFULLDEPT

TABLEACCESSFULLEMP

笛卡儿乘积(CartesianProduct)

当两个rowsource做连接,但是它们之间没有关联条件时,就会在两个rowsource中做笛卡儿乘积,这通常由编写代码疏漏造成(即程序员忘了写关联条件)。笛卡尔乘积是一个表的每一行依次与另一个表中的所有行匹配。在特殊情况下我们可以使用笛卡儿乘积,如在星形连接中,除此之外,我们要尽量避免使用笛卡儿乘积。注意在下面的语句中,在2个表之间没有连接。

在哪种情况下用哪种连接方法比较好:

1.排序--合并连接(SortMergeJoin,SMJ):

需要注意的是,以上方法并不会真正执行sql,只是产生执行计划。

例1:

假设LARGE_TABLE是一个较大的表,且username列上没有索引,则运行下面的语句:

SQL>SELECT*FROMLARGE_TABLEwhereUSERNAME=‘TEST’;

QueryPlan-----------------------------------------

SELECTSTATEMENTOptimizer=CHOOSE(Cost=1234Card=1Bytes=14)

TABLEACCESSFULLLARGE_TABLE[:Q65001][ANALYZED]

在这个例子中,TABLEACCESSFULLLARGE_TABLE是第一个操作,意思是在LARGE_TABLE表上做全表扫描。当这个操作完成之后,产生的rowsource中的数据被送往下一步骤进行处理,在此例中,SELECTSTATEMENT操作是这个查询语句的最后一步。Optimizer=CHOOSE指明这个查询的optimizer_mode,即optimizer_mode初始化参数指定的值,它并不是指语句执行时真的使用了该优化器。决定该语句使用何种优化器的唯一方法是看后面的cost部分。如果给出的是下面的形式,则表明使用的是CBO优化器,此处的cost表示优化器认为该执行计划的代价:

SELECTSTATEMENTOptimizer=CHOOSE(Cost=1234Card=1Bytes=14)假如执行计划中给出的是类似下面的信息,则表明是使用RBO优化器,因为cost部分的值为空,或者压根就没有cost部分。

例2:

假定A、B、C都是不是小表,且在A表上一个组合索引:A(a.col1,a.col2),注意a.col1列为索引的引导列。

selectA.col4fromA,B,CwhereB.col3=10andA.col1=B.col1andA.col2=C.col2andC.col3=5

ExecutionPlan----------------------------------------------------------0SELECTSTATEMENTOptimizer=CHOOSE10MERGEJOIN21SORT(JOIN)32NESTEDLOOPS43TABLEACCESS(FULL)OF'B'53TABLEACCESS(BYINDEXROWID)OF'A'65INDEX(RANGESCAN)OF'INX_COL12A'(NON-UNIQUE)71SORT(JOIN)87TABLEACCESS(FULL)OF'C'

Statistics----------------------------------------------------------0recursivecalls8dbblockgets6consistentgets0physicalreads340redosize551bytessentviaSQL*Nettoclient430bytesreceivedviaSQL*Netfromclient2SQL*Netroundtripsto/fromclient2sorts(memory)0sorts(disk)6rowsprocessed

在表做连接时,只能2个表先做连接,然后将连接后的结果作为一个rowsource,与剩下的表做连接,在上面的例子中,连接顺序为B与A先连接,然后再与C连接:

B<--->A<--->C

在执行计划中,需要知道哪个操作是先执行的,哪个操作是后执行的,这对于判断哪个表为驱动表有用处。判断之前,如果对表的访问是通过rowid,且该rowid的值是从索引扫描中来得,则将该索引扫描先从执行计划中暂时去掉。然后在执行计划剩下的部分中,判断执行顺序的指导原则就是:最右、最上的操作先执行。具体解释如下:

得到去除妨碍判断的索引扫描后的执行计划:

谈论上下关系时,只对连续的、缩进一致的行有效。

从这个图中我们可以看到,对于NESTEDLOOPS部分,最右、最上的操作是TABLEACCESS(FULL)OF'B',所以这一操作先执行,所以该操作对应的B表为第一个驱动表(外部表),自然,A表就为内部表了。从图中还可以看出,B与A表做嵌套循环后生成了新的rowsource,对该rowsource进行来排序后,与C表对应的排序了的rowsource(应用了C.col3=5限制条件)进行MSJ连接操作。所以从上面可以得出如下事实:B表先与A表做嵌套循环,然后将生成的rowsource与C表做排序—合并连接。

通过分析上面的执行计划,我们不能说C表一定在B、A表之后才被读取,事实上,B表有可能与C表同时被读入内存,因为将表中的数据读入内存的操作可能为并行的。事实上许多操作可能为交叉进行的,因为ORACLE读取数据时,如果就是需要一行数据也是将该行所在的整个数据块读入内存,而且还有可能为多块读。

看执行计划时,我们的关键不是看哪个操作先执行,哪个操作后执行,而是关键看表之间连接的顺序(如得知哪个为驱动表,这需要从操作的顺序进行判断)、使用了何种类型的关联及具体的存取路径(如判断是否利用了索引)在从执行计划中判断出哪个表为驱动表后,根据我们的知识判断该表作为驱动表(就像上面判断ABC表那样)是否合适,如果不合适,对SQL语句进行更改,使优化器可以选择正确的驱动表。

基于代价的优化器在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担。但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比。此时就需要DBA进行人为的干预,告诉优化器使用我们指定的存取路径或连接类型生成执行计划,从而使语句高效的运行。例如:对于一个特定的语句,执行全表扫描要比执行索引扫描更有效,则我们可以指示优化器使用全表扫描。在ORACLE中,是通过为语句添加hints(提示)来实现干预优化器优化的目的。

hints是oracle提供的一种机制,用来告诉优化器按照我们的告诉它的方式生成执行计划。可以用hints来实现:

THE END
1.1毫秒屏幕响应时间有什么用?华硕商城 在得物App发布了一条热门动态!快来围观,就等你啦!https://m.dewu.com/note/trend/details?id=253438965
2.内存时序解析:提升电脑性能的关键因素与选购指南首先是CAS延迟,也就是“Column Address Strobe”延迟。简单说,就是内存控制器发出读取命令后,内存芯片需要多长时间才能将数据返回给控制器。这个时间越短,内存的响应速度就越快。通常,CAS延迟的数值越小,性能越好。 接下来是RAS到CAS延迟,简称为tRCD。这项指标代表了内存芯片在行地址和列地址之间切换所需的时间。行https://news.huochengrm.cn/cygs/6344.html
3.在选择服务器时我们应该关注哪些关键参数来确保长期稳定运行除了上述因素之外,还有一点非常重要,那就是维护服务。当你购买一套完整的解决方案时,你不仅是在购买硬件,而且是在寻找未来的服务支持。因此,在选购过程中应仔细考察制造商是否提供全面的售后服务计划,并评估其响应速度和客户评价。 总结一下,当你准备为你的业务投资一套新的服务器时,你应该深入思考以下几个问题:第https://www.phb2pk42.cn/dian-ji-she-bei/684302.html
4.系统性能优化性能优化的目标:是提高系统或应用程序的响应时间、吞吐量、效率和可伸缩性等方面的性能指标。 性能优化需要有一些技巧:对于一个整个产品或项目而言,比如可以从前端优化、后端优化、架构优化、高并发优化、Linux内核优化、常用中间件优化等方便去优化,当然每个方面侧重点不同,用的技术点也不同。 https://blog.csdn.net/javajy/article/details/144394515
5.计算机性能入门:新手必读教程响应时间:指计算机对用户操作的响应速度。例如,打开一个应用程序需要的时间,或鼠标点击后到光标移动所需的时间。 吞吐量:指计算机在单位时间内能处理的任务数量。比如每分钟可以处理多少个网页请求。 可靠性:指计算机系统在运行过程中不出错的能力。如果系统频繁崩溃或数据丢失,则可靠性较低。 资源利用率:指计算机系统https://www.imooc.com/article/372069
6.运行可靠性:工业电源的关键指标评估运行可靠性的方法有多种,但统计可靠性测量,例如平均故障间隔时间 (MTBF),并不是反映实际运行寿命的良好指标。 平均故障间隔时间 (MTBF)仅提供可靠性的总体指标,并不能确定故障类型或原因。更重要的是,MTBF 通常是在受控测试条件下计算的,这些条件可能无法完全复制电源运行所处的多样性和恶劣环境。应用环境会对实https://www.eet-china.com/info/72830.html
7.常见性能指标有哪些响应时间越短,用户体验越好。通常情况下,我们希望系统的响应时间在几百毫秒以内。 2. 吞吐量(Throughput):系统在单位时间内处理的请求数量。吞吐量越高,系统处理能力越强。吞吐量通常与系统的硬件配置、网络带宽以及算法优化等因素有关。 3. 资源利用率(Resource Utilization):系统中的资源(如CPU、内存、磁盘空间等https://www.autohome.com.cn/ask/6643727.html
8.家电论坛家电家电论坛家用电器一般来说,响应时间越短越好。响应时间越短,用户在看移 动的画面时就不会出现类似残影或者拖沓的痕迹,因为按照人眼的反应时间,响应时间如果超过40毫秒,就会出现运动图像的迟滞现象,因此响应时间对于对画面 质量要求较高的用户而言,一直是非常关键的采购指标。但从目前来看,大多数液晶显示器都已经能满足用户的需要,市面http://www.360doc.com/content/07/0104/05/4910_318386.shtml
9.响应时长并非越久越佳(响应时间越短越好吗)服务器技术响应时长并非越久越佳(响应时间越短越好吗) 60Hz刷新率8ms响应时间的电视,会有拖影吗 1、从理论上讲,一般的文字处理用户,只要响应时间不超过40ms的LCD就可以接受。我们平常看到的电影,每秒钟只能显示24帧画面(1/24帧=40ms),而这时我们已经不会感觉到画面的延迟了,当画面显示速度超过每秒25帧时,人眼就会将快速https://www.kangle.im/post/107479.html
10.来定扣个人所得税,租金是越多越好还是越少越好关于我想请问一下,现在我要填写用租房的租金,来定扣个人所得税,租金是越多越好还是越少越好的律师回答 合同调解修复智囊团 帮助46869人· 响应1-3分钟内 咨询我 租房子租金可以抵扣个税,扣缴义务人办理工资、薪金所得预扣预缴税款时,应当根据纳税人报送的《个人所得税专项附加扣除信息表》(以下简称《扣除信息https://m.66law.cn/question/18294255.aspx
11.该如何选购行车记录仪?1.2场景切换响应时间据统计,有为数不少的车祸发生在高速路隧道进出口,主要是因为人眼在环境明暗突然变化时,需要一定的时间去适应环境,而在适应环境的过程中会有短暂的视觉失效或视力下降。那么行车记录能否快速响应明暗场景切换,忠实记录行车路况呢?我们使用日本京立LB-8110辉度箱LV2档模拟隧道内昏暗环境,LV10档模拟https://www.yoojia.com/ask/17-12198379082756716372.html
12.显示器响应时间越高越好?指不定也是智商税显示器响应时间越高越好?指不定也是智商税 显示器响应时间有学问,你看到的1ms可能不只是1ms那么简单…… 习惯了普遍高素质的手机屏幕,越来越多人不再满足于显示器的「能亮就行」。同时好不好、值不值的评判标准也在发生着变化。比如几年前还挺昂贵的高分辨率、高刷新率,现在是真不值钱了,但同样很重要的 1mshttp://www.dianshouit.com/thread-1010.htm
13.内脏脂肪越少越好。B. 遥信响应时间应小于1s C. 遥信响应时间应小于2s D. 遥信容量100%同时动作,不应误发、丢失遥信 查看完整题目与答案 依据<变电站数据通信网关机技术规范>Q/GDW11627-2016要求,数据通信网关机技术要求,描述不正确的是( )。 A. 采用windows操作系统 B. 采用风扇进行散热 C. 在故障、重启及切换的https://www.shuashuati.com/ti/0156d47c04fb4bb8b9fd503bdff07e0c.html
14.客服考核指标是不是越多越好?你看这几个就够啦!——九数云BI所以针对这个问题,我们可以通过考核平均响应时间该指标,约束客服回复顾客咨询过程中整体的平均响应速度。 * 平均响应时间指标的数值越小越好,反映客服回复顾客消息的整体快慢。 03-客服考核指标:问答比 指标概念:答问比=客服消息数/顾客消息数; 指标算法: https://www.jiushuyun.com/other/14347.html
15.千牛工作台怎么回复顾客?有什么原则?1、响应时间越短越好 实践证明如果一位买家进入店铺咨询后在30秒内没有得回复,就可能会走人,因为买家没有那么多时间等待。如果买家在发了问题后30秒仍不见回复,他就可能会看店里其他宝贝或者跳到别家店铺去。所以客服人员一定要在最短的时间内回复买家,最好能把时间控制的越短越好。 https://www.maijia.com/article/557183
16.显示器响应时间是什么意思?显示器响应时间5ms和1ms有什么差别我们在选购显示器的时候,经常会关注显示器尺寸、面板类型、屏幕比例、分辨率、接口等参数,不过对于游戏玩家更在意的是刷新率与响应时间等参数。关于刷新率知识已经科普了多次,相信不少玩家对刷新率参数有所了解。那么显示器响应时间是什么意思?显示器响应时间5ms和1ms有什么差别?针对这两个问题,下面装机之家来科普一下http://www.lotpc.com/yjzs/8246.html
17.液晶显示屏模组主要参数亮度:亮度是指屏幕发出的光的强度。亮度越高,屏幕在强光环境下的可见度就越好。然而,过高的亮度也可能导致屏幕漏光或降低画质。 响应时间:响应时间是指液晶模组从接收到信号到显示出相应图像所需的时间。响应时间越短,屏幕在显示动态图像时的拖影现象就越少,画面就越流畅。 https://b2b.baidu.com/q/aland?q=1B73776E061D03770F080D6A1E201F3E1B637B070334&id=qidfcd347f2a69e6b3281c8b31af56cb64f&answer=10136930018394132403&utype=2
18.淘宝客服平均响应时间影响客服响应的因素客服平均响应时间是指客服在回复客户的过程中,从客户的咨询到客服的回复的每一次时间差的均值,当然,这个数值要越小越好,这项数据可以帮助店铺分析客服的响应速度够不够及时,一般小型的店铺接待量200-300的话,客服的平就响应时间是16秒左右。 影响这个标准的因素有很多,主要涉及到以下几点:https://www.mmker.cn/article/19857.html
19.监视器技术固定刷新率和gsync选择哪个监视器刷新率越高越好吗监视器的刷新率越高并不总是越好,因为最适合你的刷新率取决于你的使用需求和硬件配置。 高刷新率可以提供更平滑和流畅的图像,尤其在高速场景中,如快速移动的游戏画面。这对于竞技游戏、FPS游戏或其他需要迅速反应的游戏来说是非常重要的。高刷新率可以减少画面撕裂(Tearing)和模糊感,提供更好的反应时间,带来更好的https://m.elecfans.com/article/2245623.html
20.无线传输速率是不是越大越好随着科技的不断发展,我们对无线传输速率的需求也越来越高。无线传输速率指的是无线网络传输数据的速度,通常以Mbps(兆位每秒)为单位。在选择无线网络设备或者订购网络服务时,我们会关注其传输速率的大小,常常认为速率越大越好。然而,无线传输速率是否真的越大越好呢?本文将从不同的角度来探讨这个问题。 https://www.chugeyun.com/news/12655.html