SQL脚本存在TABLE ACCESS FULL行为及其优化
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集群。
学问:纸上得来终觉浅,绝知此事要躬行
为事:工欲善其事,必先利其器。
态度:道阻且长,行则将至;行而不辍,未来可期
.....................................................................
------- 桃之夭夭,灼灼其华。之子于归,宜其室家。 ---------------
------- 桃之夭夭,有蕡其实。之子于归,宜其家室。 ---------------
------- 桃之夭夭,其叶蓁蓁。之子于归,宜其家人。 ---------------
=====================================================================
* 博客文章部分截图及内容来自于学习的书本及相应培训课程以及网络其他博客,仅做学习讨论之用,不做商业用途。
* 如有侵权,马上联系我,我立马删除对应链接。 * @author Alan -liu * @Email no008@foxmail.com
转载请标注出处! ✧*꧁一品堂.技术学习笔记꧂*✧. ---> https://www.cnblogs.com/ios9/