设为首页 收藏本站
查看: 1148|回复: 0

[经验分享] Oracle Index

[复制链接]

尚未签到

发表于 2018-9-25 10:46:01 | 显示全部楼层 |阅读模式
Oracle Index 介绍概述    索引在各种关系型数据库系统中都是举足轻重的组成部分,其对于提高检索数据的速度起至关重要的作用。在Oracle中,索引基本分为以下几种:B*Tree索引,反向索引,降序索引,位图索引,函数索引,interMedia全文索引等。  Oracle提供了大量索引选项。知道在给定条件下使用哪个选项对于一个应用程序的性能来说非常重要。一个错误的选择可能会引发死锁,并导致数据库性能急剧下降或进程终止。而如果做出正确的选择,则可以合理使用资源,使那些已经运行了几个小时甚至几天的进程在几分钟得以完成,这样会使您立刻成为一位英雄。这篇文章就将简单的讨论每个索引选项。主要有以下内容:
  [1] 基本的索引概念
  查询DBA_INDEXES视图可得到表中所有索引的列表,注意只能通过USER_INDEXES的方法来检索模式(schema)的索引。访问USER_IND_COLUMNS视图可得到一个给定表中被索引的特定列。
  [2] 组合索引
  当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在 Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。
  特别注意:在Oracle9i之前,只有在使用到索引的前导索引时才可以使用组合索引!
  [3] ORACLE ROWID
  通过每个行的ROWID,索引Oracle提供了访问单行数据的能力。ROWID其实就是直接指向单独行的线路图。如果想检查重复值或是其他对ROWID本身的引用,可以在任何表中使用和指定rowid列。
  [4] 限制索引
  限制索引是一些没有经验的开发人员经常犯的错误之一。在SQL中有很多陷阱会使一些索引无法使用。下面讨论一些常见的问题:
  4.1 使用不等于操作符(、!=)
  下面的查询即使在cust_rating列有一个索引,查询语句仍然执行一次全表扫描。
  select cust_Id,cust_name
  from  customers
  where cust_rating  'aa';
  把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。
  select cust_Id,cust_name
  from  customers
  where cust_rating < 'aa' or cust_rating > 'aa';
  特别注意:通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描。
  4.2 使用IS NULL 或IS NOT NULL
  使用IS NULL 或IS NOT NULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。
  4.3 使用函数
  如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。
  下面的查询不会使用索引(只要它不是基于函数的索引)
  select empno,ename,deptno
  from  emp
  where trunc(hiredate)='01-MAY-81';
  把上面的语句改成下面的语句,这样就可以通过索引进行查找。
  select empno,ename,deptno
  from  emp
  where hiredate  索引的二元高度对把ROWID返回给用户进程时所要求的I/O量起到关键作用。在对一个索引进行分析后,可以通过查询DBA_INDEXES的B-level列查看它的二元高度。二元高度主要随着表的大小以及被索引的列中值的范围的狭窄程度而变化。索引上如果有大量被删除的行,它的二元高度也会增加。更新索引列也类似于删除操作,因为它增加了已删除键的数目。重建索引可能会降低二元高度。
  [8] 快速全局扫描
  在Oracle7.3后就可以使用快速全局扫描(Fast Full Scan)这个选项。这个选项允许Oracle执行一个全局索引扫描操作。快速全局扫描读取B-树索引上所有树叶块。初始化文件中的DB_FILE_MULTIBLOCK_READ_COUNT参数可以控制同时被读取的块的数目。
  [9] 跳跃式扫描
  从Oracle9i开始,索引跳跃式扫描特性可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。索引跳跃式扫描比全索引扫描要快的多。下面的程序清单显示出性能的差别:
  create index skip1 on emp5(job,empno);
  index created.
  select count(*)
  from emp5
  where empno=7900;
  Elapsed:00:00:03.13
  Execution Plan
  0   SELECT STATEMENT Optimizer=CHOOSE(Cost=4 Card=1 Bytes=5)
  1 0  SORT(AGGREGATE)
  2 1   INDEX(FAST FULL SCAN) OF 'SKIP1'(NON-UNIQUE)
  Statistics
  6826 consistent gets
  6819 physical  reads
  select /*+ index(emp5 skip1)*/ count(*)
  from emp5
  where empno=7900;
  Elapsed:00:00:00.56
  Execution Plan
  0   SELECT STATEMENT Optimizer=CHOOSE(Cost=6 Card=1 Bytes=5)
  1 0  SORT(AGGREGATE)
  2 1   INDEX(SKIP SCAN) OF 'SKIP1'(NON-UNIQUE)
  Statistics
  21 consistent gets
  17 physical  reads
  [10] 索引的类型
  B-树索引
  位图索引
  HASH索引
  索引编排表
  反转键索引
  基于函数的索引
  分区索引
  本地和全局索引
  简要解释:
  b*tree index:几乎所有的关系型数据库中都有b*tree类型索引,也是被最多使用的。其树结构与二叉树比较类似,根据rid快速定位所访问的行。
  反向索引:反转了b*tree索引码中的字节,是索引条目分配更均匀,多用于并行服务器环境下,用于减少索引叶的竞争。
  降序索引:8i中新出现的索引类型,针对逆向排序的查询。
  位图索引:使用位图来管理与数据行的对应关系,多用于OLAP系统。
  函数索引:这种索引中保存了数据列基于function返回的值,在select * from table where function(column)=value这种类型的语句中起作用。
  B*Tree索引
  B*Tree索引是最常见的索引结构,默认建立的索引就是这种类型的索引。B*Tree索引在检索高基数数据列(高基数数据列是指该列有很多不同的值)时提供了最好的性能。当取出的行数占总行数比例较小时B-Tree索引比全表检索提供了更有效的方法。但当检查的范围超过表的10%时就不能提高取回数据的性能。B-Tree索引是基于二叉树的,由分支块(branch block)和叶块(leaf block)组成。在树结构中,位于最底层底块被称为叶块,包含每个被索引列的值和行所对应的rowid。在叶节点的上面是分支块,用来导航结构,包含了索引列(关键字)范围和另一索引块的地址。
  假设我们要找索引中值为80的行,从索引树的最上层入口开始,定位到大于等于50,然后往左找,找到第2个分支块,定位为75-100,最后再定位到叶块上,找到80所对应的rowid,然后根据rowid去读取数据块获取数据。如果查询条件是范围选择的,比如where column >20 and column  select 'number',dump(1,16) from dual
  union all select 'number',dump(2,16) from dual
  union all select 'number',dump(3,16) from dual;
  'NUMBE DUMP(1,16)
  ------ -----------------
  number Typ=2 Len=2: c1,2 (1)
  number Typ=2 Len=2: c1,3 (2)
  number Typ=2 Len=2: c1,4 (3)
  再对比一下反向以后的情况:
  SQL> select 'number',dump(reverse(1),16) from dual
  2 union all select 'number',dump(reverse(2),16) from dual
  3 union all select 'number',dump(reverse(3),16) from dual;
  'NUMBE DUMP(REVERSE(1),1
  ------ -----------------
  number Typ=2 Len=2: 2,c1 (1)
  number Typ=2 Len=2: 3,c1 (2)
  number Typ=2 Len=2: 4,c1 (3)
  我们发现索引码的结构整个颠倒过来了,这样1,2,3个索引码基本上不会出现在同一个叶块里,所以减少了争用。不过反向索引又一个缺点就是不能在所有使用常规索引的地方使用。在范围搜索中其不能被使用,例如,where column>value,因为在索引的叶块中索引码没有分类,所以不能通过搜索相邻叶块完成区域扫描。
  降序索引
  降序索引是8i里面新出现的一种索引,是B*Tree的另一个衍生物,它的变化就是列在索引中的储存方式从升序变成了降序,在某些场合下降序索引将会起作用。举个例子,我们来查询一张表并进行排序:
  SQL> select * from test where a between 1 and 100 order by a desc,b asc;
  已选择100行。
  Execution Plan
  ----------------------------------------------------------
  0    SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=100 Bytes=400)
  1 0 SORT(ORDER BY)(Cost=2 Card=100 Bytes=400)
  2 1 INDEX (RANGE SCAN) OF 'IND_BT' (NON-UNIQUE) (Cost=2 Card=100 Bytes=400)
  这里优化器首先选择了一个索引范围扫描,然后还有一个排序的步骤。如果使用了降序索引,排序的过程会被取消。
  SQL> create index test.ind_desc on test.testrev(a desc,b asc);
  索引已创建。
  SQL> analyze index test.ind_desc compute statistics;
  索引已分析
  再来看下执行路径:
  SQL> select * from test where a between 1 and 100 order by a desc,b asc;
  已选择100行。
  Execution Plan(SQL执行计划,稍后会讲解如何使用)。
  ----------------------------------------------------------
  0    SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=100 Bytes=400)
  1 0 INDEX (RANGE SCAN) OF 'IND_DESC' (NON-UNIQUE) (Cost=2 Card=100 Bytes=400)
  我们看到排序过程消失了,这是因为创建降序索引时Oracle已经把数据都按降序排好了。
  另外一个需要注意的地方是要设置init.ora里面的compatible参数为8.1.0或以上,否则创建时desc关键字将被忽略。
  位图索引
  位图索引主要用于决策支持系统或静态数据,不支持行级锁定。位图索引最好用于低cardinality列(即列的唯一值除以行数为一个很小的值,接近零),例如又一个“性别”列,列值有“Male”,“Female”,“Null”等3种,但一共有300万条记录,那么3/3000000约等于0,这种情况下最适合用位图索引。
  位图索引可以是简单的(单列)也可以是连接的(多列),但在实践中绝大多数是简单的。在这些列上多位图索引可以与AND或OR操作符结合使用。位图索引使用位图作为键值,对于表中的每一数据行位图包含了TRUE(1)、FALSE(0)、或NULL值。位图索引的位图存放在B-Tree结构的页节点中。B-Tree结构使查找位图非常方便和快速。另外,位图以一种压缩格式存放,因此占用的磁盘空间比B-Tree索引要小得多。位图索引的格式如表26-1所示。
  表26-1 位图索引的格式
  行
  值 1 2 3 4 5 6 7 8 9 10
  Male 1 0 0 0 0 0 0 0 1 1
  Female 0 1 1 1 0 0 1 1 0 0
  Null 0 0 0 0 1 1 0 0 0 0
  如果搜索where gender=’Male’,要统计性别是”Male”的列行数的话,Oracle很快就能从位图中找到共3行即第1,9,10行是符合条件的;如果要搜索where gender=’Male’ or gender=’Female’的列的行数的话,也很容易从位图中找到共8行即1,2,3,4,7,8,9,10行是符合条件的。如果要搜索表的值的话,那么Oracle会用内部的转换函数将位图中的相关信息转换成rowid来访问数据块。
  函数索引
  基于函数的索引也是8i以来的新产物,它有索引计算列的能力,它易于使用并且提供计算好的值,在不修改应用程序的逻辑上提高了查询性能。使用基于函数的索引有几个先决条件:
  1)必须拥有QUERY REWRITE(本模式下)或GLOBAL QUERY REWRITE(其他模式下)权限。
  2)必须使用基于成本的优化器,基于规则的优化器将被忽略。
  3)必须设置以下两个系统参数:
  QUERY_REWRITE_ENABLED=TRUE
  QUERY_REWRITE_INTEGRITY=TRUSTED
  可以通过alter system set,alter session set在系统级或线程级设置,也可以通过在init.ora添加实现。
  这里举一个基于函数的索引的例子:
  SQL> create index test.ind_fun on test.testindex(upper(a));
  索引已创建。
  SQL> insert into testindex values('a',2);
  已创建 1 行。
  SQL> commit;
  提交完成。
  SQL> select /*+ RULE*/* FROM test.testindex where upper(a)='A';
  A       B
  -- ----------
  a       2
  Execution Plan
  ----------------------------------------------------------
  0  SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX'
  (优化器选择了全表扫描)
  --------------------------------------------------------------------
  SQL> select * FROM test.testindex where upper(a)='A';
  A       B
  -- ----------
  a       2
  Execution Plan
  ----------------------------------------------------------
  0  SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=5)
  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TESTINDEX' (Cost=2 Card=
  1 Bytes=5)
  2    1     INDEX (RANGE SCAN) OF 'IND_FUN' (NON-UNIQUE) (Cost=1 Car
  d=1)(使用了ind_fun索引)
  各种索引的创建方法
  (1)*Tree索引。
  Create index indexname on tablename(columnname[columnname...])
  (2)反向索引。
  Create index indexname on tablename(columnname[columnname...]) reverse
  (3)降序索引。
  Create index indexname on tablename(columnname DESC[columnname...])
  (4)位图索引。
  Create BITMAP index indexname on tablename(columnname[columnname...])
  (5)函数索引。
  Create index indexname on tablename(functionname(columnname))
  注意:创建索引后分析要索引才能起作用。
  analyze index indexname compute statistics;
  各种索引使用场合及建议
  (1)B*Tree索引。
  常规索引,多用于oltp系统,快速定位行,应建立于高cardinality列(即列的唯一值除以行数为一个很大的值,存在很少的相同值)。
  (2)反向索引。
  B*Tree的衍生产物,应用于特殊场合,在ops环境加序列增加的列上建立,不适合做区域扫描。
  (3)降序索引。
  B*Tree的衍生产物,应用于有降序排列的搜索语句中,索引中储存了降序排列的索引码,提供了快速的降序搜索。
  (4)位图索引。
  位图方式管理的索引,适用于OLAP(在线分析)和DSS(决策处理)系统,应建立于低cardinality列,适合集中读取,不适合插入和修改,提供比B*Tree索引更节省的空间。
  (5)函数索引。
  B*Tree的衍生产物,应用于查询语句条件列上包含函数的情况,索引中储存了经过函数计算的索引码值。可以在不修改应用程序的基础上能提高查询效率。
  索引什么时候不工作
  首先要声明两个知识点:
  (1)RBO&CBO。
  Oracle有两种执行优化器,一种是RBO(Rule Based Optimizer)基于规则的优化器,这种优化器是基于sql语句写法选择执行路径的;另一种是CBO(Cost Based Optimizer)基于代价的优化器,这种优化器是Oracle根据统计分析信息来选择执行路径,如果表和索引没有进行分析,Oracle将会使用RBO代替CBO;如果表和索引很久未分析,CBO也有可能选择错误执行路径,不过CBO是Oracle发展的方向,自8i版本来已经逐渐取代RBO.
  (2)AUTOTRACE。
  要看索引是否被使用我们要借助Oracle的一个叫做AUTOTRACE功能,它显示了sql语句的执行路径,我们能看到Oracle内部是怎么执行sql的,这是一个非常好的辅助工具,在sql调优里广泛被运用。我们来看一下怎么运用AUTOTRACE:
  ① 由于AUTOTRACE自动为用户指定了Execution Plan,因此该用户使用AUTOTRACE前必须已经建立了PLAN_TABLE。如果没有的话,请运行utlxplan.sql脚本(它在$ORACLE_HOME/rdbms/admin目录中)。
  ② AUTOTRACE可以通过运行plustrce.sql脚本(它在$ORACLE_HOME/sqlplus/admin目录中)来设置,用sys用户登陆然后运行plustrce.sql后会建立一个PLUSTRACE角色,然后给相关用户授予PLUSTRACE角色,然后这些用户就可以使用AUTOTRACE功能了。
  ③ AUTOTRACE的默认使用方法是set autotrace on,但是这方法不总是适合各种场合,特别当返回行数很多的时候。Set autotrace traceonly提供了只查看统计信息而不查询数据的功能。
  SQL> set autotrace on
  SQL> select * from test;
  A
  ----------
  1
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE
  1    0   TABLE ACCESS (FULL) OF 'TEST'
  Statistics
  ----------------------------------------------------------
  0 recursive calls
  0 db block gets
  0 consistent gets
  0 physical reads

  0 redo>  0 bytes sent via SQL*Net to client
  0 bytes received via SQL*Net from client
  0 SQL*Net roundtrips to/from client
  0 sorts (memory)
  0 sorts (disk)
  rows processed
  SQL> set autotrace traceonly
  SQL> select * from test.test;
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE
  1    0   TABLE ACCESS (FULL) OF 'TEST'
  Statistics
  ----------------------------------------------------------
  0 recursive calls
  0 db block gets
  0 consistent gets
  0 physical reads

  0 redo>  0 bytes sent via SQL*Net to client
  0 bytes received via SQL*Net from client
  0 SQL*Net roundtrips to/from client
  0 sorts (memory)
  0 sorts (disk)
  rows processed
  Hints是Oracle提供的一个辅助用法,按字面理解就是‘提示’的意思,确实它起得作用也是提示优化器按它所提供的关键字来选择执行路径,特别适用于sql调整的时候。使用方法如下:
  {DELETE|INSERT|SELECT|UPDATE} /*+ hint [text] [hint[text]]... */
  具体可参考Oracle SQL Reference。
  有了前面这些知识点,接下来让我们来看一下什么时候索引是不起作用的。以下列出几种情况。
  (1)类型不匹配时。
  SQL> create table test.testindex (a varchar(2),b number);
  表已创建。
  SQL> create index ind_cola on test.testindex(a);
  索引已创建。
  SQL> insert into test.testindex values('1',1);
  已创建 1 行。
  SQL> commit;
  提交完成。
  SQL> analyze table test.testindex compute statistics for all indexes;
  表已分析。
  SQL> set autotrace on;
  SQL> select /*+RULE */* FROM test.testindex where a='1';(使用基于rule的优化器,数据类型匹配的情况下)
  A           B
  -- ----------
  1           1
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TESTINDEX'
  2    1     INDEX (RANGE SCAN) OF 'IND_COLA' (NON-UNIQUE)(使用了索引ind_cola)
  ――――――――――――――――――――――――――――――――――
  SQL> select /*+RULE */* FROM test.testindex where a=1;(数据类型不匹配的情况)
  A           B
  -- ----------
  1           1
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX'(优化器选择了全表扫描)
  (2)条件列包含函数但没有创建函数索引。
  SQL> select /*+ RULE */* FROM test.testindex where upper(a)= 'A';(使用了函数upper()在列a上);
  A           B
  -- ----------
  a           2
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX'(优化器选择全表扫描)
  ----------------------------------------------------------
  创建基于函数的索引
  SQL> create index test.ind_fun on test.testindex(upper(a));
  索引已创建。
  SQL> insert into testindex values('a',2);
  已创建1行。
  SQL> commit;
  提交完成。
  SQL> select /*+ RULE*/* FROM test.testindex where upper(a)='A';
  A           B
  -- ----------
  a           2
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX'
  (在RULE优化器下忽略了函数索引选择了全表扫描)
  -----------------------------------------------------------
  SQL> select * FROM test.testindex where upper(a)
  ='A';
  A           B
  -- ----------
  a           2
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=5)
  1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TESTINDEX' (Cost=2 Card=
  1 Bytes=5)
  2    1     INDEX (RANGE SCAN) OF 'IND_FUN' (NON-UNIQUE) (Cost=1 Car
  d=1)(CBO优化器使用了ind_fun索引)
  (3)复合索引中的前导列没有被作为查询条件。
  创建一个复合索引
  SQL> create index ind_com on test.testindex(a,b);
  索引已创建。
  SQL> select /*+ RULE*/* from test.testindex where a='1';
  A           B
  -- ----------
  1           2
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   INDEX (RANGE SCAN) OF 'IND_COM' (NON-UNIQUE)(条件列表包含前导列时使用索引ind_com)
  SQL> select /*+ RULE*/* from test.testindex where b=1;
  未选定行
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=HINT: RULE
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX'(条件列表不包括前导列是选择全表扫描)
  -----------------------------------------------------------
  (4)CBO模式下选择的行数比例过大,优化器采取了全表扫描。
  SQL> select * from test.testindex where a='1';
  A           B
  -- ----------
  1           2
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=5)
  1    0   TABLE ACCESS (FULL) OF 'TESTINDEX' (Cost=1 Card=1 Bytes=5)
  (表一共2行,选择比例为50%,所以优化器选择了全表扫描)
  ――――――――――――――――――――――――――――――――――
  下面增加表行数
  SQL> declare i number;
  2 begin
  3 for i in 1 .. 100 loop
  4 insert into test.testindex values (to_char(i),i);
  5 end loop;
  6 end;
  7 /
  PL/SQL 过程已成功完成。
  SQL> commit;
  提交完成。
  SQL> select count(*) from test.testindex;
  COUNT(*)
  ----------
  102
  SQL> select * from test.testindex where a='1';
  A             B
  ---- ----------
  1             1
  1             2
  Execution Plan
  SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1 Bytes=5)
  1    0   INDEX (RANGE SCAN) OF 'IND_COM' (NON-UNIQUE) (Cost=1 Card=1 Bytes=5)
  (表一共102行,选择比例为2/102=2%,所以优化器选择了索引扫描)
  (5)CBO模式下表很久没分析,表的增长明显,优化器采取了全表扫描。
  SQL> select * from test.testindex where a like '1%';
  A             B
  ---- ----------
  1             2
  1             1
  10           10
  11           11
  12           12
  13           13
  14           14
  15           15
  16           16
  17           17
  18           18
  19           19
  100         100
  已选择13行。
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=13 Bytes=52)
  1   0 TABLE ACCESS (FULL) OF 'TESTINDEX' (Cost=1 Card=13 Bytes=52)
  (表一共102行,选择比例为13/102>10%,优化器选择了全表扫描)
  ――――――――――――――――――――――――――――――――――
  增加表行数
  SQL> declare i number;
  2 begin
  3 for i in 200 .. 1000 loop
  4 insert into test.testindex values (to_char(i),i);
  5 end loop;
  6 end;
  7 /
  PL/SQL 过程已成功完成。
  SQL> commit;
  提交完成。
  SQL> select count(*) from test.testindex;
  COUNT(*)
  ----------
  903
  SQL> select * from test.testindex where a like '1%';
  A             B
  ---- ----------
  1             2
  1             1
  10           10
  11           11
  12           12
  13           13
  14           14
  15           15
  16           16
  17           17
  18           18
  19           19
  100          100
  1000         1000
  已选择14行。
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=13 Bytes=52)
  1 0 TABLE ACCESS (FULL) OF 'TESTINDEX' (Cost=1 Card=13 Bytes=52)
  (表一共903行,选择比例为14/903 analyze table test.testindex compute statistics for table for all indexed c
  olumns for all indexes;
  表已分析。
  SQL> select * from test.testindex where a like '1%';
  A             B
  ---- ----------
  1             2
  1             1
  10           10
  100         100
  1000       1000
  11           11
  12           12
  13           13
  14           14
  15           15
  16           16
  17           17
  18           18
  19           19
  已选择14行。
  Execution Plan
  ----------------------------------------------------------
  0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=24 Bytes=120)
  1   0 TABLE ACCESS (BY INDEX ROWID) OF 'TESTINDEX' (Cost=4 Card=
  24 Bytes=120)
  2 1 INDEX (RANGE SCAN) OF 'IND_COLA' (NON-UNIQUE) (Cost=2 Ca
  rd=24)
  (经过分析后优化器选择了正确的路径,使用了ind_cola索引)


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-601468-1-1.html 上篇帖子: ORACLE ERP 的前世今生(5) 下篇帖子: Oracle 表
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表