网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > 数据库 > Oracle教程
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
数据库:数据库教程,数据库技巧,Oracle教程,MySQL教程,Sybase教程,Access教程,DB2教程,数据库安全,数据库文摘
本月文章推荐
.linux下的应用开发起步--简化蚂蚁.
.HP和Oracle使用Fusion来溶合SOA.
.在多个目录之中自动搜索需要的文.
.如何为oracle中的表增加像sql se.
.ORACLE与SQL Server之间的数据迁.
.怎么样格式化磁盘.
.详细介绍oracle数据库字符集.
.Oracle DBA 用户管理试题选.
.数据库Oracle9i的企业管理器简介.
.ORA-03113错误分析与解决.
.OracleORA-00903错误具体原因分析.
.Oracle9i初始化参数中文说明8.
.Oracle中备份控制文件和启动参数.
.Linux上的sysctl.
.优化Oracle停机时间及数据库恢复.
.ORACLE常用傻瓜問題1000問(之十一.
.深入讲解"alert log"过大时的处理.
.Oracle10G R2(10.2.0.1)在AIX5.2.
.自动清除statspack所产生的snaps.
.浅析Oracle和SqlServer存储过程的.

索引什么时候不工作

发表日期:2008-2-9


首先要声明两个知识点: (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 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调整的时候。使用方法如下: {DELETEINSERTSELECTUPDATE} /*+ 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<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索引)
上一篇:Oracle优化经典文章--磁盘I/O和碎片篇 人气:917
下一篇:oracle数据库-关于索引 人气:1316
浏览全部Oracle教程的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐