`
hypgr
  • 浏览: 277870 次
社区版块
存档分类
最新评论

索引什么时候不工作

阅读更多

首先要声明两个知识点:

1RBO&CBO

Oracle

有两种执行优化器,一种是RBO(Rule Based Optimizer)基于规则的优化器,这种优化器是基于sql语句写法选择执行路径的;另一种是CBOCost Based Optimizer)基于规则的优化器,这种优化器是Oracle根据统计分析信息来选择执行路径,如果表和索引没有进行分析,Oracle将会使用RBO代替CBO;如果表和索引很久未分析,CBO也有可能选择错误执行路径,不过CBOOracle发展的方向,自8i版本来已经逐渐取代RBO.

2AUTOTRACE

要看索引是否被使用我们要借助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 size
          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 size
          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'(
条件列表不包括前导列是选择全表扫描)
-----------------------------------------------------------

4CBO模式下选择的行数比例过大,优化器采取了全表扫描。

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%,所以优化器选择了索引扫描)

5CBO模式下表很久没分析,表的增长明显,优化器采取了全表扫描。

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<5%,优化器选择了全表扫描,选择路径是错误的)
―――――――――――――――――――――――――――――
给表做分析

SQL> 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 楼 liushilang 2009-10-26  
其中有些情况与我实际上有点不同,不知道什么原因

相关推荐

    oracle 性能调整 sql性能优化大全

    `索引什么时候不工作 工作 时候 索引 SQL test_testindex 选择 优化 OF Optimizer _中国网管联盟-网管网-bitsCN_com.htm`可能解释了某些情况下,如全索引扫描、索引覆盖不完全、动态SQL或使用绑定变量时,索引可能...

    SQLSEVER索引和索引调整向导

    因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,选择创建索引的列时,可以参考以下的原则: * 在经常需要搜索的列上创建索引,加快搜索的速度。 * 在作为主键的...

    为什么有时ORACLE数据库不用索引来查找数据.doc

    Oracle数据库在某些情况下选择不使用索引来查找数据,这一现象与数据库的优化器策略密切相关。Oracle数据库有两种主要的优化器:基于规则的优化器(RBO)和基于代价的优化器(CBO)。RBO遵循固定规则,而CBO自Oracle...

    表和索引统计信息不一致

    在数据库管理中,"表和索引统计信息不一致"是一个常见的问题,它涉及到数据库的性能优化和查询效率。统计信息是数据库管理系统用于优化查询计划的重要依据,包括表的行数、列的值分布情况以及索引的使用情况等。当...

    69 更新数据的时候,自动维护的聚簇索引到底是什么?l.pdf

    聚簇索引是数据库索引技术中的一种特殊类型,它在数据表中直接存储了数据行,并且这些数据行是按照聚簇索引的...理解聚簇索引的工作原理和维护机制可以帮助数据库管理员和开发人员更好地管理数据库性能和数据完整性。

    nexus index 索引手动更新

    总之,掌握手动更新Nexus索引的技巧,对于经常使用Nexus的开发团队来说是非常有价值的,它可以提高工作效率,确保团队始终能够快速访问到仓库中的最新组件。同时,了解并利用好提供的相关资源,如压缩包中的文档和...

    80设计索引的时候,我们一般要考虑哪些因素呢?(下).pdf

    例如,如果一个性别字段只有“男”和“女”两种值,建立索引后的性能提升可能就不明显。一般而言,基数越高的字段建立索引后效果越好。 关于前缀索引,当字段包含较长的字符串时,创建索引可能会占用大量空间。这时...

    存储系统之索引

    - **早期阶段**:在计算机刚起步的时候,数据量较小,对于索引的需求并不明显。 - **关系型数据库阶段**:随着数据量的激增,关系型数据库成为主流,对索引的需求也随之增加。这一时期,B树及其变种如B+树和B*树成为...

    创建索引的作用利弊

    - **CREATE TABLE时定义:** 在创建表的时候直接指定索引,如:`CREATE TABLE table_name (..., column_name ..., INDEX index_name (column_name));` **2.2 特殊类型的索引:** - **唯一索引(UNIQUE INDEX):**...

    优化SQL Server索引的小技巧

    如果你运行这个向导,你会看到关于数据库中关于索引的统计量,这些统计量作为日志工作并定时更新,这样就减轻了手工重建索引所带来的工作量。如果你不想自动维护索引,那么你可以手工重建索引,并在需要时执行 ...

    76当我们在SQL里进行分组的时候,如何才能使用索引?.pdf

    理解索引的工作原理以及如何在SQL语句中合理使用索引,对于提升数据库的性能和效率至关重要。在进行索引设计和查询优化时,需要全面考虑查询模式、索引结构以及数据更新的影响,综合运用各种优化策略以达到最优的...

    Excel-VBA宏编程实例源代码-获取索引所指定的工作表名.zip

    例如,你可能需要遍历整个工作簿,对每个工作表执行相同的操作,这时候就可以利用`For Each...Next`循环来实现: ```vba Sub 遍历工作表() Dim ws As Worksheet For Each ws In ThisWorkbook.Worksheets MsgBox ...

    SQL中索引的原理.doc

    此外,有时候组合使用聚集索引和非聚集索引会得到更好的性能效果,例如在使用一个聚集索引进行范围查询的同时,利用非聚集索引来加速其他列的查询。 在建立索引时,还需要考虑数据的分布情况。如果数据分布呈现高度...

    行业-69 更新数据的时候,自动维护的聚簇索引到底是什么?l.rar

    与聚簇索引相对的是非聚簇索引(Non-Clustered Index),非聚簇索引并不影响数据的物理存储顺序,它只是一个指向实际数据行的指针列表。一个表可以有多个非聚簇索引,但每次查询时,非聚簇索引需要通过索引找到对应...

    10.MySQL为什么有时候会选错索引?1

    当表的数据发生变化时,如大量插入或删除操作,优化器可能无法准确预估扫描行数,从而做出不理想的索引选择。 首先,我们需要理解MySQL优化器的工作原理。优化器的主要任务是分析查询语句,并根据表的统计信息和...

    UITableView汽车名牌带右侧索引

    要实现这样的功能,开发者首先需要理解UITableView的基本工作原理。UITableView由多个Section组成,每个Section下包含多行Row。在本案例中,汽车品牌可以按照字母顺序分配到不同的Section,每个Section对应一个字母...

    行业-78设计索引的时候,我们一般要考虑哪些因素呢?(上).rar

    这是一项持续的工作,旨在确保系统的性能随着业务需求的变化而保持最优。 综上所述,设计索引时需要综合考虑查询性能、数据访问模式、数据分布、存储空间、复合索引以及数据库系统特性等多个因素。只有深入理解这些...

    Oracle Spatial空间索引 解析

    有时候,为了获得最佳性能,可以同时使用R树索引和四叉树索引,这可以通过设置参数实现。Oracle Spatial设计时考虑了这一点,提供了灵活的索引管理选项。 综上所述,Oracle Spatial通过其完备的组件和索引机制为...

    行业-75当我们在SQL里进行排序的时候,如何才能使用索引?.rar

    首先,我们需要理解索引的工作原理。索引是一种特殊的数据结构,它为表中的列创建了一个指向实际数据行的指针列表。这个指针列表是按照列值的顺序排列的,使得数据库可以快速查找特定值或范围内的值。在大多数关系型...

    行业-80设计索引的时候,我们一般要考虑哪些因素呢?(下).rar

    5. **可维护性**:设计索引需考虑未来的维护工作。使用清晰的代码风格,编写详细的文档,实施版本控制,以及设计灵活的模块化结构,都能提高代码的可维护性。 6. **兼容性**:在多平台、多设备的环境下,设计索引...

Global site tag (gtag.js) - Google Analytics