SQL脚本存在TABLE ACCESS FULL行为
对于SQL的执行计划,一般尽量避免TABLE ACCESS FULL的出现,那怎样去定位,系统里面哪些SQL脚本存在TABLE ACCESS FULL行为,对于9i及以后版本,使用以下语句即可
select *
from v$sql_plan v
where v.operation = 'TABLE ACCESS'
and v.OPTIONS = 'FULL'
and v.OBJECT_OWNER='MS';--指定用户下
查询得到SQL_ID,以及ADDRESS,HASH_VALUE,PLAN_HASH_VALUE,OBJECT_NAME后,就可以定位到具体的SQL语句了。
如:
select s.SQL_TEXT
from v$sqlarea s
where s.SQL_ID = '4dpd97jh2gzsd'
and s.HASH_VALUE = '1613233933'
and s.PLAN_HASH_VALUE = '3592287464';
或者
select s.SQL_TEXT from v$sqlarea s where s.ADDRESS = '00000000A65D2318';
ORACLE优化之执行规划 - TABLE FULL SCAN/INDEX FULL SCAN
TABLE FULL SCAN : 全表扫描,表示表中所有记录都被访问到。如果表很大, 该操作对查询性能的影响会很大,此时,建议使用索引 或去掉查询中的LIKE操作。
如:
EXPLAIN PLAN
SET statement_id = 'ex_plan1' FOR
SELECT phone_number FROM employees
WHERE phone_number LIKE '650%';
INDEX RANGE SCAN [DESCENDING] : 从相关索引中获取了一个或多个ROWID。 当查询条件字段具有非唯一索引,或者查询过滤条件是一个范围, ORACLE将会采用该操作。
示例:
SELECT * FROM t_employee WHERE id > 11001;
SELECT * FROM t_employee WHERE first_name = 'Tommy';
此例中,id是关键字,first_name具有非唯一索引。 oracle会对此两个索引采用INDEX RANGE SCAN.
INDEX FULL SCAN [DESCENDING]: 从相关的索引中获取了所有的ROWID。由于是按索引的顺序访问和获取ROWID, 因此获得的ROWID是直接排过序的。
示例1:
SELECT /*+ INDEX(T_EMPLOYEE IDX_NODES_ID)*/ id from T_EMPLOYEE;
示例中使用了HINT要求强制使用索引查询,但未指定索引字段的过滤条件, 于是ORACLE将采用INDEX FULL SCAN操作。由于该操作按索引顺序或去记录, 因而返回的ID列表是排过序的。
示例2:
SELECT * FROM T_EMPLOYEE WHERE MIDDLE_NAME IS NULL;
当MIDDLE_NAME字段可以为NULL,且具有非唯一索引,ORACLE在执行此语句时, 可能会采用INDEX FULL SCAN操作。 但在某些情况下,比如该语句已经执行过一遍,相关数据已经加载到内存, 那么,ORACLE的执行规划也可能会直接选择TABLE FULL SCAN操作,可能 是ORACLE认为此时直接TABLE FULL SCAN的性能会比INDEX FULL SCAN高。
INDEX FAST FULL SCAN
从相关索引中获取所有的ROWID。该操作同时从多个索引数据块中扫描数据, 所以结果并不是排序的。用于对索引字段进行查询。
示例:SELECT id FROM T_EMPLOYEE; 其中id为表的主键索引字段。
优化策略:
一般情况下,尽量避免FULL SCAN,特别是TABLE FULL SCAN和INDEX FULL SCAN. 在查询大表的情况下,INDEX RANGE SCAN会显著提高查询性能。但在查询小表时, INDEX可能反而对性能产生不利影响。
oracle创建索引
数据库索引是为了提高查询速度的一种数据结构。
索引的创建语句
索引的创建语句非常简单。
CREATE INDEX 索引名 ON 表名(列名);
除了单列索引,还可以创建包含多个列的复合索引。
CREATE INDEX 索引名 ON 表名(列名1, 列名2, 列名3, ...);
删除索引也非常简单。
DROP INDEX 索引名;
查看某个表中的所有索引也同样简单。
SELECT * FROM ALL_INDEXES WHERE TABLE_NAME = '表名'
还可以查看某个表中建立了索引的所有列。
SELECT * FROM ALL_IND_COLUMNS WHERE TABLE_NAME = '表名'
索引的建立原则
1.索引应该建立在WHERE子句中经常使用的列上。如果某个大表经常使用某个字段进行查询,并且检索的啊行数小于总表行数的5%,则应该考虑在该列上建立索引。
2.对于两个表连接的字段,应该建立索引。
3.如果经常在某表的一个字段上进行Order By的话,则也应该在这个列上建立索引。
4.不应该在小表上建立索引。
索引的优缺点
索引主要是为了提高数据的查询速度,这就是索引的优点。但是当进行增删改的时候,会更新索引。因此索引越多,增删改的速度就会越慢,因为有一个维护索引的过程。创建索引之前需要权衡该字段是否经常发生增删改操作,否则可能会带来负优化的问题。
索引的优点
1.很大地提高了数据的检索速度。
2.创建唯一索引能保证数据库表中每一行数据的唯一性(唯一性约束)。
3.提高表与表之间的连接速度。
索引的缺点
1.索引需要占用物理空间。
2.当对表中的数据进行增加、删除和修改的时候,索引也要动态地进行维护,降低数据的维护速度。
关于查询优化器
当Oracle拿到SQL语句的时候,会使用查询优化器去分析该语句,并根据分析结果生成查询执行计划。也就是说,数据库是执行的查询计划,而不是SQL语句。
查询优化器有RBO(Rule-Based-Optimizer,基于规则的查询优化器)和CBO(Cost-Based-Optimizer,基于成本的查询优化器),其中基于规则的查询优化器在10g的版本中彻底消失了。原因是因为RBO最后的查询都是全表扫描,而CBO会根据统计信息选择最优的查询方案。
因此,CBO一旦发现有索引的存在,并且这个索引能帮助提高查询速度,就是使用通过索引进行查询的方法。
oracle 索引的几种类型
1. b-tree索引
Oracle数据库中最常见的索引类型是b-tree索引,也就是B-树索引,以其同名的计算科学结构命名。CREATE
INDEX语句时,默认就是在创建b-tree索引。没有特别规定可用于任何情况。
2. 位图索引(bitmap index)
位图索引特定于该列只有几个枚举值的情况,比如性别字段,标示字段比如只有0和1的情况。
3. 基于函数的索引
比如经常对某个字段做查询的时候是带函数操作的,那么此时建一个函数索引就有价值了。
4. 分区索引和全局索引
这2个是用于分区表的时候。前者是分区内索引,后者是全表索引
5. 反向索引(REVERSE)
这个索引不常见,但是特定情况特别有效,比如一个varchar(5)位字段(员工编号)含值
(10001,10002,10033,10005,10016..)
这种情况默认索引分布过于密集,不能利用好服务器的并行
但是反向之后10001,20001,33001,50001,61001就有了一个很好的分布,能高效的利用好并行运算。
6.HASH索引
HASH索引可能是访问数据库中数据的最快方法,但它也有自身的缺点。集群键上不同值的数目必须在创建HASH集群之前就要知道。需要在创建HASH集群的时候指定这个值。使用HASH索引必须要使用HASH集群。