经典Oralce-SQL语句优化_第1页
经典Oralce-SQL语句优化_第2页
经典Oralce-SQL语句优化_第3页
经典Oralce-SQL语句优化_第4页
经典Oralce-SQL语句优化_第5页
已阅读5页,还剩99页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

SQL语句处理过程1、OpenCursor2、ParseStatement3、ExecuteStatement4、FetchValueFromCursorParseStatement搜索LibraryCache检查语法检查数据源获取分析锁检查权限确定执行规划ExecuteStatement给绑定变量赋值(Attention)应用执行计划进行必要的I/O和排序动作AfterExecute从查询获得结果,并将结果传给变量。将SQL执行规划放在LibraryCache将从数据库获取的数据(表及索引中间结果)放在BufferCacheSQL共享为了不重复解析相同的SQL语句,在第一次解析之后,Oracle将SQL语句存放在内存中。这块位于系统全局区域SGA的共享池中的内存可以被所有的数据库用户共享。因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同,Oracle就能很快获得已经被解析的语句以及执行路径。Oracle的这个功能大大地提高了SQL的分析性能并节省了内存的使用。当你向Oracle提交一个SQL语句,Oracle会首先在这块内存中查找相同的语句。这里需要注明的是,Oracle对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,大小写,换行等)。共享的语句必须满足三个条件:1、字符级的比较当前被执行的语句和共享池中的语句必须完全相同,如以下三条SQL不能共享:Select...FromEmpSelect...FromEmpSelect...FromEmp2、所指的对象必须完全相同用户A:Select...FromEmp用户BSelect...FromEmp这两条SQL由于所指对象是各用户的,对象不同,虽然SQL完全相同,但却不能共享。3、使用相同的名字的绑定变量以下两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)Selectpin,nameFrompeopleWherepin=:blk1.ot_ind;Selectpin,nameFrompeopleWherepin=:blk1.ov_ind;共享SQL优势:减少Parse动态调整内存增进内存使用效率在Oracle9i系统中,将参数Cursor_Sharing设为Similar或Force,则优化器会自动地将数值转化为绑定变量,如:SelectNameFromEmpWhereID=1234;SelectNameFromEmpWhereID=5678;转化为:SelectNameFromEmpWhereID=:SYS_B_O从而共享语句。

注意:由于对绑定变量的赋值是在SQL语句的执行阶段,而执行规划的制定是在分析阶段,因此,使用绑定变量有可能使得制定的执行规划并不是最优的执行规划,或者对于某些值是优秀的执行规划,而对于其它值则不是。(基于CBO优化器)

举例如下:Trans表有几百万条数据,列Status有两种值,1与0,决大多数为前者,0只有100条,语句Select...FromTransWhereStatus=:v_sta如果采用全表扫描,当Status值为0,就不是最优执行规划;而如果用索引扫描,当status值为1,就会出现问题。如果不使用绑定变量,当使用CBO优化器时,并且表(包含列)分析过,优化器就会参照Histogram信息,制定正确执行规划。如果使用绑定变量,则无论如何都不会参照Histogram信息。对于OLTP类型数据库,Cursor_Sharing设Similar、Force有助于提升性能,特别是基于RBO优化方法。而对数据仓库,则Cursor_Sharing应为Exact。这是由于内存对数据仓库不是问题,而性能至关重要。在Oracle9i之前,对于绑定变量,由于在评估之前,无法知道变量值,值只在执行计划已制定后才传给游标,在这种情况下,优化器很可能做出错误选择。在Oracle9i,分析语句之前,优化器会首先查看PGA中绑定变量值,再制定执行规划(通过参数_potim_peek_user_binds控制)。注意:以上只适用于Hard_Parse情况,即执行规划根据第一个绑定变量值确定。Explain方案的解释规则由里到外,由高到低。“由里到外”不能违反“由高到低”Selectstatement5nestedloops4tableaccessfullsales1tableaccessbyrowid3indexuniquescan2And-EuqalSelect/...+And_Euqal(T1I1I2).../C1FromT1WhereC1=0AndC2=0SelectStatementTableAccess(ByIndexRowid)Of'T1'

And-EQUAL

Index(RangeScan)Of'I1'Index(RangeScan)Of'I2'在合并索引的情况下,驱动索引的选择对于性能有很大的影响。一般优化器选择Where条件第一个索引作为驱动索引。以上SQL,如果列C2选择性比C1强,则条件改为:WhereC2=0AndC1=0性能会更好。BitmapAndSelect/...+Index_Combine(T1I1I2).../C1,C2FromT1WhereC1=0AndC2=0SelectStatementBitmapConversion(ToRowids)

BitmapAnd

BitmapIndexOf'I1'BitmapIndexOf'I2'CONCATENATIONSelect/...+Use_Concat.../C1FromT1WhereC2=0OrC3=0SelectStatement

CONCATENATION

TableAccess(Full)Of'T1'TableAccess(Full)Of'T1'CONNECTBYSelectC1,C2FromT1ConnectByC1=PriorC2StartWithC1=0;SelectStatement

CONNECTBY

TableAccess(Full)Of'T1'TableAccess(ByUserRowid)Of'T1'TableAccess(Full)Of'T1'COUNT(STOPKEY)SelectRownumFromT1WhereRownum<10;SelectStatement

Count(Stopkey)

TableAccess(Full)Of'T1'FILTERSelectC2FromT1WhereExist(SelectC1FromT2WhereT1.C1=T2.C1)SelectStatement

FILTER

TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'HashJoinSelect/...+Use_Hash(T1T2).../T1.C2,T2.C2FromT1,T2WhereT1.C1=T2.C1SelectStatement

HashJoin

TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'HashJoin(Anti)SelectC2FromT1WhereC1NotIn(Select/...+Hash_AJ.../C1FromT2)SelectStatement

HashJoin(Anti)

TableAccess(Full)Of'T1'ViewOf'VW_NSO_1'TableAccess(Full)Of'T2'HashJoin(Semi)SelectC2FromT1WhereExists(Select/...+Hash_sj.../C1FromT2WhereT1.C1=T2.C1)SelectStatement

HashJoin(Semi)

TableAccess(Full)Of'T1''T1'TableAccess(Full)Of'T1''T2'

IndexFastFullScanSelect/...+Index_Ffs(T1I1).../C1FromT1WhereC1IsNotNullSelectStatementIndex(FastFullScan)Of'I1'IndexSkipScanCreateIndexI1OnT1(C1,C2)Select/...+Index_SS(T1I1).../C1FromT1WhereC2=0;SelectStatement

Index(SkipScan)Of'I1‘只在9i才实现,只适用于首列值数量有限的情况。对首列的每个值,使用选择的尾随列查找索引。IndexUniqueScanSelect/...+Index(T1I1).../C1FromT1WhereC1=10;SelectStatement

Index(UniqueScan)Of'I1'InlistIteratorSelectC1FromT1WhereC1IN(10,20,30,40)SelectStatement

InlistIterator

Index(RangeScan)Of'I1'MERGEJoinSelect/...+Use_Merge(T1T2).../T1.C2,T2.C2FromT1,T2WhereT1.C1=T2.C1;SelectStatement

MergeJoinSort(Join)TableAccess(Full)Of'T1'Sort(Join)TableAccess(Full)Of'T2'MergeJoinAntiSelectC2FromT1WhereC1NotIn(Select/...+Merge_AJ.../C1FromT2)SelectStatement

MergeJoin(Anti)

Sort(Join)TableAccess(Full)Of'T1'Sort(Unique)ViewOf'VW_NSO_1'TableAccess(Full)Of'T2'MergeJoinSemiSelectC2FromT1WhereC1Exists(Select/...+MERGE_SJ.../C1FromT2WhereT1.C1=T2.C1);SelectStatement

MergeJoin(Semi)

Sort(Join)TableAccess(Full)Of'T1'Sort(Unique)TableAccess(Full)Of'T2'NestedLoopsSelect/...+Use_nl(T1T2).../T1.C2,T2.C2FromT1,T2WhereT1.C1=T2.C1SelectStatement

NestedLoops

TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'NestedLoopsAntiSelectC2FromT1WhereC1NotIn(Select/...+NL_AJ.../C1FromT2)SelectStatementNestedLoops(Anti)TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'NestedLoopsSemiSelectC2FromT1WhereExists(Select/...+NL_SJ.../C1FromT2WhereT1.C1=T2.C1);SelectStatement

NestedLoops(Semi)

TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'PartitionRangeAllSelectC1FromT1;SelectStatement

PartitionRange(All)

TableAccess(Full)Of'T1'PartitionRangeInlistSelectC1FromT1WhereC1IN(10,20);SelectStatement

PartitionRange(Inlist)

TableAccess(Full)Of'T1'PartitionRangeIteratorSelectC1FromT1WhereC1>8AndC1<12;SelectStatement

PartitionRange(Iterator)

TableAccess(Full)Of'T1'Sort(Join)Select/...+Use_Merge(T1T2).../T1.C2,T2.C2FromT1,T2WhereT1.C1=T2.C1;SelectStatementMergeJoin

Sort(Join)TableAccess(Full)Of'T1'

Sort(Join)TableAccess(Full)Of'T2'TableAccessByIndexRowidSelectC2FromT1WhereC1=0;SelectStatementTableAccess(BYIndexRowid)Index(RangeScan)Of'I1'TableAccessFullSelectC1FromT1;SelectStatement

TableAccess(Full)Of'T1'

Union-AllSelectC1FromT1UnionAllSelectC1FromT2;SelectStatement

Union-All

TableAccess(Full)Of'T1'TableAccess(Full)Of'T2'ViewSelect/...+No_Merge(v1).../...From(SelectC1FromT1)v1;SelectStatement

View

TableAccess(Full)Of'T1'Hint使用Hint只能用于Delete、Update、Select之后,Update语句则忽略Hint。Hint只对其存放的部分有效,放在子查询中只对子查询有效;放在主查询中只对主查询有效;放在Union查询中只对其存放部分有效。如果语句使用Alias,则在Hint引用表时必须引用Alias,而不能引用表名。对于多个Hint中间用空格分开。All_Rows、First_Rows:使用CBO并分别以最佳吞吐量和最短反应时间为目标,不管是否含有分析数据。And_Equal(TableIndex1Index2...):使用索引合并。Append:使用DirectLoad方法,直接插入表末尾,高位标志之后。Tablespace、Table必须用Nologging选项创建。Cache(Table):将通过全表扫描的表放在LRU列表前端。Full(Table):强迫对指定表进行全表扫描。Hash_AJ、Merge_AJ:强迫反联结语句(含有NotIn、NotExists的语句)使用HashJoin、MergeJoin、NestedLoops。提示必须放在子句中。或者将参数Always_Anti_Join设为Merge或Hash。Hash_SJ、Merge_SJ:使用半联结(对于含有In、Exists子查询,首先消除内部表的冗余值,再使用联结)。或者将参数Always_Semi_Join设为Merge或Hash。提示必须放在子句中。Index(TableIndex):强迫对指定表进行索引扫描。Index_Desc(TableIndex):强迫索引降序扫描。默认使用升序扫描。Index_Ffs(TableIndex):强迫索引全扫描,而不是表全扫描。与Index全扫描不同,快速全扫描可以使用多块读技术。Merge(Table):合并视图。与No_Merge相反。NoIndex(TableIndex)禁止使用索引。NoReWrite禁止查询重写。如使用物化视图进行查询重写。Ordered要求按From语句中表的顺序对表进行连接,忽略表的索引等级。ReWrite:使用物化视图进行查询重写。Leading(Table)指定联结次序中的首表。Use_Hash(Table1Table2)、Use_Merge(Table1Table2)、Use_NL(Table1Table2):分别使用HashJoin、MergeJoin、NestedLoops。查询转换简单视图合并,视图合并步骤如下:1、将主查询涉及的视图用视图中的基表替代。2、对主查询的视图选择列、视图条件列用视图基表列替代。3、将视图的Where条件加到主查询的Where条件中。4、将视图GroupBy与Having条件附到Where条件之后。合并后的表的顺序与视图中的表的顺序相同。复杂视图合并:视图中必须包含Union,ConnectBy,Distinct,GroupBy,Rownum,以及汇集函数。主要是为了避免出现:Max(Max(Val))9i加入Merge提示才能部分实现。谓词下推和上移:复杂查询往往包含多个视图与子查询,在这些视图和子查询中包含多个谓词。Oracle可将谓词移入或移出视图,以产生新的高效查询。如:CreateViewEmp_AggAsSelectDeptno,Avg(Sal)Avg_SalFromEmpGroupByDeptno;SQL:SelectDeptno,Avg_SalFromEmp_AggWhereDeptno=10;Oracle会将谓词Deptno=10推进该视图,将查询转换为:SelectDeptno,Avg(Sal)FromEmpWhereDeptno=10GroupByDeptno;子查询“展平”:将不同类型的子查询转变为联接、半联接或反联接。主要用于含:In、NotIn、Exist、NotExist的语句。“半联接”是一种特殊类型的联接,适用于含有In或Exists的语句,它消除了联接中来自内表的冗余值RBO:基于规则优化器以一套预先定义的规则确定SQL语句对数据库的访问路径在以下情况下RDBMS内核会使用RBO:Optimizer_Mode=RuleOptimizer_Mode=Choose并且From语句涉及的表全部都没分析过,且不包含除Rule外的其它Hint。使用提示Select/...+Rule.../

CBO:基于成本优化器CBO优化器使用数据字典表:DBA_TableS,DBA_Index,DBA_TAB_Columns查询到的信息进行成本估价,进而构造出最优的执行计划。默认情况下以最佳吞吐量为目标。注意:如果优化程序对SQL选择基于开销的方法,并且该语句所涉及的表没有任何统计数据,那么优化程序将使用内部信息(诸如分配给表盘区数)来估计其他统计信息。在下列情况下使用CBO优化器:Optimizer_Mode=Choose,并且至少一个表曾经分析过,优化器选择基于开销的方法,并以最佳吞吐量为目标。Optimizer_Mode=First_Rows或All_Rows,不管数据字典中是否存在统计信息,优化器都将选择基于开销的方法,前者以最佳响应时间为目标,而后者则以最佳吞吐量为目标。除Rule之外提示,如Select/...+First_Rows.../。CBO执行规划制定查询转换:包括视图合并;子查询转换为联结;用实体化视图进行查询重写成本评估:主要是对选择性、基数、开销进行评估。产生规划程序,比较成本,产生最优执行计划。Analyze命令:AnalyzeTableEmpEstimateStatisticsSample5PercentForAllIndexedColumns;AnalyzeIndexEmp_indEstimateStatisticsSample5PercentForAllIndexedColumns;AnalyzeTableEmpComputeStatisticsForAllIndexedColumns;AnalyzeTableEmpDeleteStatistics;以下参数将影响RBO制定规划:Compatible:设为当前版本可使优化器有效得利用当前版本的新特性。Sort_Area_Size,越低越有可能采用NestedLoops。Hash_Area_Size,一般为排序区2倍,为使用散列联结,至少要1M,同时Hash_Join_Enabled为True。Optimizer_Mode_Enable,启用新优化器特性,比如8.1.7Optimize_Index_Caching,值范围0—100之间。比如50,它将告诉优化器有50%索引扫描需要的数据会在内存中Optimizer_Index_Cost_Adj,正常值为100,可设低于或高于100。比如10,表示优化器在估计索引扫描的开销时,将其定为正常值的10%。Query_Rewrite_Enable,启用基于函数索引,以及使用物化视图进行查询重写功能Always_Semi_Join,该参数主要用于调解含Exists的语句。Always_Anti_Join,该参数主要用于调解含NotIn的语句。为使用如下数据库功能,必须使用CBO:StoredOutline、HashJoin、IOT、Function-BasedIndex、MaterializedViews、BitmapIndex、Histogram、Hints。如果表未分析过,为使用以上功能项,必须使用Hint。Hint能够激活CBO,并使用内部信息(诸如分配给表盘区数)进行数据收集。RBO选择索引规则:唯一性索引对于多列索引,列数越多,级别越高单列索引等式匹配比不等式匹配或模糊匹配的等级要高如果用到的索引都是单列非唯一性索引,则优化器选择合并索引。

RBO联结规则在索引等级相同的情况下,不同表联结顺序如下:From语句从右至左;同一张表Where条件应用顺序从左至右。Where条件中,有索引的非联结条件优于联结条件,无有索引的非联结条件的情况下,根据From顺序结合联结条件确定联结顺序;

无索引的非联结条件可以被忽略。表的优先级表的优先级与Where条件中涉及索引的优先级相关联。Where条件中对主键与唯一性索引引用使得包含该索引的表优先于其它包含非唯一性索引的表。Where条件包含对所有索引列的等式引用,将优先于只对部分列的引用。Where条件中含有对双列索引全部列的引用,将优先于对两个单列索引的引用。同等条件下列在From语句最后一位的表将作为驱动表,而不是按索引时间。根据Rowid访问单行簇联结主键单行访问基于主键或唯一键的单行访问簇表联结优于非簇表联结多列索引优于单列索引索引列的有界范围扫描与LIKE‘A%’。索引列无界范围扫描。索引列的ORDERBY。全表扫描。NestedLoop驱动表的全表扫描或索引扫描被驱动表的索引扫描发现匹配,通过被驱动表的RowID访问TableAccessFullIndexSCANTableAccessBYRowidNESTEDLOOPOracle假定Nested_Loop优于MergeJoin;如果采用Nested_Loop,由于被驱动表必须有索引,因此,即使在Where子句中只有对该表索引列的约束条件,而非联结条件的情况下,优化器仍然选择其它表作为驱动表。驱动表选择(对于涉及到联结的两张同时包含索引的情况):根据包含在Where条件中的表的索引的选择性以及涉及的列的数量和匹配条件选择驱动表。当驱动表只返回一行时(唯一性索引),优化程序会选择对被驱动表进行全表扫描。Nested_Loop特征联结性能的关键是表联结的次序。与Nested_Loop有关的提示包括:Ordered,Full,Index,Use_nl。改变索引的可用性,也会影响Nested_Loop驱动表的选择。常用方法包括:对数字或日期型的列加零,对字符型加空格。MergeJoin对联结的每个表进行TableAccessFull进行SortJoin,对以上结果进行排序。进行MergeJoin,将SortJoin结果合并。TableAccessFullTableAccessFullSortJoinSortJoinMergeJoinMergeJoin特征从查询返回第一行较慢。(集操作)它的结果集不会缓存在SGA。处理查询也许需要分配临时段。适用于全表扫描比索引扫描更可取的情况。如:表很小,一次物理读可完成;对于多表联结,如果联结表在联结条件及非联结条件中无任何有索引的约束条件,优化器将选择MergeJoin;HashJoin在HashJoin里,两个表都被全表扫描。Oracle读取涉及联结的其中一个表,并在内存创建来自表的联结列的值的位图。随着行的读取,它们按联结关键字被分组送入散列功能分区。对第二张表执行同样的散列功能分区,同时,第一张表创建的位图被用作过滤器。HashJoin联结性能要比MergeJoin好。特别是非常巨大的表。HashJoin只对等式联结有效,而对于不等或范围联结则无效;而对MergeJoin,等式联结与不等式及范围联结都有效。

联结顺序假设表T1、T2、t3,每个表有记录100000条,按NAME均匀分部,每NAME值有10条记录,每100条记录占1数据块,每张表占1000个数据块。每个表在NAME,SALARY列都建有索引。SQL:Select...fromT1,T2,t3whereT1.name=T2.nameandT2.name=andT1.salary=1000andt3.salary=2000联结顺序有6种。T1.salary=10006条t3.salary=2000100条顺序T1、T2、T3访问T1(通过SALARY索引访问),需3+6个逻辑IO。访问T2(通过NAME索引访问):6...3+6...10访问T3(通过SALARY索引访问):3+100总共需190逻辑IO。顺序T1、T3、T2访问T1(通过SALARY索引访问),需3+6个逻辑IO。访问T3(通过SALARY索引访问):3+100如果T3(通过NAME索引访问):6...13T1、T3联结结果记录数在0--60之间,因此,访问T2(通过NAME索引访问)地IO在0到60...3+60...10之间。而为0概率很大。总共IO可能为:87或112顺序T2、T1、T3T2全表扫描需10000个物理IOT1索引扫描(通过SALARY索引访问),需3+6个逻辑IO。T3索引扫描(通过SALARY索引访问),3+100个逻辑IO。总IO量非常大。T2、T1、T3之间通过Hash联结,如果采用NESTEDLOOP,T1逻辑IO将超过30000。顺序T2、T3、T1T2全表扫描需10000个物理IOT3索引扫描(通过SALARY索引访问),3+100个逻辑IO。T1索引扫描(通过SALARY索引访问),需3+6个逻辑IO。总IO量非常大。T2、T1、T3之间通过Hash联结,如果采用NESTEDLOOP,T1逻辑IO将超过30000。顺序T3、T2、T1访问T3(通过SALARY索引访问):3+100访问T2(通过NAME索引访问):13...100访问T1(通过SALARY索引访问),需3+6总共需1412IO顺序T3、T1、T2访问T3(通过SALARY索引访问),需103个逻辑IO。访问T1(通过SALARY索引访问):3+6如果T3(通过NAME索引访问):100...13T1、T3联结结果记录数在0--60之间,因此,访问T2(通过NAME索引访问)地IO在0到60...3+60...10之间。而为0概率很大。总共IO可能为:112多表联结顺序规则选择返回行比较少,并且,有等式联结条件的表作为联结第一张表。如果第一张表的等式联结条件与多个表相联系,应选择返回中间结果较少的表作为联结第二张表。根据联结条件依次选择第三、四表。选择联结顺序时,可适当参照索引,尽量避免全表扫描。分步式查询优化如果Oracle需要多个远程表,优化程序首先确定所有表是否在同一位置,如果在同一位置,将整个查询送到远程站点,只返回最终结果集;如果远程表在多个位置,优化程序将查询分解为多个SQL,分别访问远程表,将中间结果返回本地进行联结。联结执行的位置以称驱动站点。对于远程表,用户只能使用联结次序和联结操作提示,而不能使用访问方法提示。对基于RBO的优化器,由于本地优化程序无法知道远程表的索引情况,只会以“对远程表进行全表扫描”制定执行计划。对远程表实际操作方法根据语句传送到远程后再具体决定。对基于CBO的优化器,本地优化程序能够知道是否存在可用的远程表索引,能够制定更优的执行规则。对基于RBO的优化程序,如果本地表在联结列上建有索引,优化程序将以远程表为驱动表,与本地表进行NestedLoops。如果本地表在联结列上无索引,一般是采取MergeJoin。如果非联结约束条件有对本地表Unique索引全部列等式引用(即:只返回一行),优化器将以本地表为驱动表,与远程表进行NestedLoops。SQL:SelectDname,EnameFromDept,Emp@RemWhereDept.Deptno=Emp.Deptno将被分解为(MergeJoin):SelectDeptno,DnameFromDept(本地执行);SelectDeptno,EnameFromEmp(远程执行)。或分解为(使用NestedLoop):SelectDeptno,DnameFromDeptWhereDeptno=:1(在本地执行),SelectDeptno,EnameFromEmp(远程执行)。在远程:CreateViewDept_EmpAsSelectDname,EnameFromDept@Local,EmpWhereDept.Deptno=Emp.Deptno在本地:Select...FromDept_Emp@Rem优化程序将本地表Dept发送到远程数据库,只联结结果返回本地。与SQL:Select/...+Driving_site(b).../Dname,EnameFromDepta,Emp@RembWherea.Deptno=b.Deptno执行规划相同。OuterJoin基于RBO优化器下,优化器选择不含(+)的表作为驱动表进行NestedLoop,因此,我们又称返回所有行的表为驱动表。由于外联结的返回结果与普通联结的返回结果不同,因此,不同的联结顺序产生的结果也不同,这防碍了视图合并。外联结表的所有条件(联结或非联结)都必须是(+)格式,SQL就不是外,它可转换为普通联结:SelectA.Name,B.Address,C.SesFromTest1A,Test2B,Test3CWhereA.Name(+)=B.NameAndA.Num=C.NumExists与InExists相对于IN有两点优势:值传递;会尽可能使用索引进行存在判断Exists只要发现关系成立,子查询就中止。而IN无论如何都要完全子查询操作。在执行步骤上,Exists语句是外部表驱动内部表的存在判断;而对于IN语句,则是内部表先执行,再以内部表作为驱动表,进行NestedLoop。由于Exists是由外表驱动内表做存在判断,因此,对于外表较小而内表较大的情况使用Exists较好;而IN则是由内表驱动外表做NestedLoop,因此,对于内表较小的情况使用IN较好。具体好坏要参照索引状况。优化在对待子查询时一般将其转化为连接查询,因此在写语句时尽可能用连接替换子查询。特别是MergeJoin或HashJoin比NestedLoop联结效果更好的地方。索引失效问题Select...FromEmpWhereTo_Char(ID)=‘123’使用全表扫描。Select...FromEmpWhereID=To_Number(‘123’)使用索引扫描。Select...FromEmpWhereIDNot=0使用全表扫描。Select...FromEmpWhereName||‘’=‘ABC’使用全表扫描。Select...FromEmpWhereName=‘ABC’||‘DEF’使用索引扫描。Select...FromEmpOrderByName使用索引扫描。Select...FromEmpOrderByTo_Char(Name)使用全表扫描。

隐式数据类型转换:默认转换类型是:字符->数值,字符―>Date;即等式两边如果发生类型不一致,则优先选择将字符类型转换为数值类型或Date。如以下语句:Select...FromEmpWhereID=‘123’(ID=To_Number(‘123’))使用索引扫描。Select...FromEmpWhereName=123(隐含To_Number(Name)=123)使用全表扫描。对于Like类型的查询,Select...FromEmpWhereIDlike‘123%’不会用到索引,这是因为ID为Number类型。这是由于Like只对字符类型的有用。常用优化技巧Union、OR与IN一般情况下,用OR或IN替换Union会取得更好的性能,这是由于使用Union会产生对同一操作对象的多次扫描。OR与IN在执行性能上是相同的,但在功能上并不完全相同,虽然在有些场合是可相互替换的。Select...FromT1WhereC1IN(1,2)进行二次索引扫描(C1有索引)或一次全表扫描。Select...FromT1WhereC1=1OrC2(C1)=2;进行二次索引扫描(都有索引)或一次全表扫描(至少一个无索引)。Select...FromT1WhereC1=1UnionSelect...FromT1WhereC1(C2)=12;进行二次索引扫描(都有索引)或一次全表扫描与索引扫描(一个无索引)或二次全表扫描(都无索引,即使是同一列)。如果确实要用Union,将结果较小的表放在前面,这样有利于节省内存消耗。如果你坚持要用Or,那就需要返回记录最少的索引列写在最前

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论