SQL脚本存在TABLE ACCESS FULL行为及其优化

Posted ✧*꧁一品堂.技术学习笔记꧂*✧.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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集群。

以上是关于SQL脚本存在TABLE ACCESS FULL行为及其优化的主要内容,如果未能解决你的问题,请参考以下文章

SQL FULL JOIN 关键字

SQL Full Join 关键字

Access 可以像 SQL Server 一样生成 CREATE TABLE 脚本代码吗?

在 Access DB 上执行 sql 脚本

MS Access SQL 将行转换为列

sql语句中的full join具体是怎么回事啊?