Oracle 查询优化器 -- 访问路径
来源:互联网 发布:遇见未知的自己 知乎 编辑:程序博客网 时间:2024/05/18 04:54
-- Start
全表扫描(full table scans)
不要以为全表扫描就一定慢, 全表扫描时, 由于数据块在磁盘中是连续的,Oracle 可以一次读取多个块来提高查询效率,至于多少个块,是由 DB_FILE_MULTIBLOCK_READ_COUNT 决定的。所以,如果你需要返回一个表的大部分数据,全表扫描要比索引扫描快。除此之外,Oracle 会自动对小表进行全表扫描,那什么是小表呢?就是语句块小于 DB_FILE_MULTIBLOCK_READ_COUNT 定义的值。如果你想让 Oracle 使用全表扫描,你也可以通过下面的方式指示 Oracle 使用全表扫描。
select /* FULL(t)*/ * from test t where col = 'test';
索引扫描(index scans)
你有没有想过,我们通过索引扫描时,如何通过索引定位到表中的位置呢?答案是通过 Rowid, Rowid 是 Oracle 内部使用的,用来标示行存储地址,所以通过 Rowid 定位行记录是最快的。有一点特别需要注意,Oracle 读写磁盘的最小单位是块,一个块可能包含多行,所以全表扫描还是索引扫描取决于访问块的百分比,而不是行的百分比。假设我们现在需要访问 3 行,这 3 行可能在一个块中,也可能在两个块中,还可能在三个块中,很明显,最理想的情况是在一个块中,Oracle 使用索引聚簇因子(index clustering factor)来衡量这种特性。索引聚簇因子越高,表明 Oracle 通过 Rowid 访问行的代价就越高。此外,Oracle 会根据索引类型的不同,是否排序,采用不同的索引扫描方式。唯一索引扫描(Index Unique Scans)
如果你的查询条件有等价操作符(=),且恰好能用到唯一索引,那么 Oracle 会采用唯一索引扫描,当然你也可以通过下面的方式建议 Oracle 采用哪个索引。
select /* INDEX(t test_id_pk)*/ * from test t where col = 'test';
索引范围扫描(Index Range Scans)
如果你的查询条件有范围操作符(>,>=,<,<=,like 'abc%'),且恰好能用到索引,那么 Oracle 会采用索引范围扫描,当然你也可以通过下面的方式建议 Oracle 采用哪个索引。select /* INDEX(t test_id_pk)*/ * from test t where col = 'test';
索引降序范围扫描(Index Range Scans Descending)
如果你的查询条件有范围操作符且要求用索引列排序,那么 Oracle 会采用索引降序范围扫描,这样做的好处是 Oracle 可以省略排序这个非常耗时的步骤。当然你也可以通过下面的方式建议 Oracle 采用索引降序范围扫描。如果你的索引是升序的。select /* INDEX_DESC(t test_id_pk)*/ * from test t where col = 'test';如果你的索引是降序的。select /* INDEX_ASC(t test_id_pk)*/ * from test t where col = 'test';
索引跳跃扫描(Index Skip Scans)
如果你的索引是复合索引,也就是索引包含多个列,如下所示。CREATE INDEX cust_idx ON customers (gender, email);
而你的查询语句没有用到索引的第一列 gender,只用到了第二列 email, 如下所示。
SELECT * FROM customers WHERE email = 'wave0409@163.com';
由于性别列(gender)只有男女两个值,Oracle 会采用如下的方式做查询。
SELECT * FROM customers WHERE gender='M' AND email = 'wave0409@163.com';UNION ALLSELECT * FROM customers WHERE gender='F' AND email = 'wave0409@163.com';
Oracle 把这种查询方式叫做索引跳跃扫描,需要注意的是这种方式只适合像性别这样,值非常少的列,你也可以通过下面的方式建议 Oracle 采用索引跳跃扫描。
select /* INDEX_SS(t test_id_idx)*/ * from test t where col = 'test';select /* INDEX_SS_ASC(t test_id_idx)*/ * from test t where col = 'test';select /* INDEX_SS_DESC(t test_id_idx)*/ * from test t where col = 'test';
全索引扫描(Full Scans)
如果你的查询需要排序或分组,且排序或分组用到的列恰好是索引列,那么 Oracle 会采用全索引扫描,由于索引列是有序的,这样 Oracle 可以省略排序这个非常耗时的步骤。快速全索引扫描(Fast Full Index Scans)
如果你要查询的所有列都包含在索引中,Oracle 就不需要访问表了,这样 Oracle 就可能通过并行和一次读取多个块来提高查询索引的效率。你也可以通过下面的方式建议 Oracle 采用快速全索引扫描。select /* INDEX_FFS(t test_id_pk)*/ * from test t where col = 'test';
索引连接扫描(Index Joins)
如果你的表有多个索引,恰好你要查询的所有列包含在这些索引中,Oracle 就不需要访问表了,Oracle 只需要把这些索引连接起来。你也可以通过下面的方式建议 Oracle 采用索引连接。select /* INDEX_JOIN(t test_id_idx test_name_idx)*/ * from test t where col = 'test';
位图索引扫描(Bitmap Indexes)
如果你的表定义了位图索引,Oracle 会使用位图索引来做查询,你也可以通过下面的方式建议 Oracle 采用位图索引扫描。select /* INDEX_COMBINE(t test_idx1 test_idx2)*/ * from test t where col = 'test';
索引聚簇扫描(Indexed Cluster Access)
如果你的表包含在了某个索引聚簇中,Oracle 会使用索引聚簇来执行查询。Hash 聚簇扫描(Hash Cluster Access)
如果你的表包含在了某个Hash 聚簇中,Oracle 会使用 Hash 聚簇来执行查询。采样扫描(Sample Table Scans)
如果你的查询语句包含 SAMPLE 子句,那么 Oracle 会使用 采样扫描。--更多参见:Oracle SQL 优化精萃
-- 声明:转载请注明出处
-- Last edited on 2015-08-28
-- Created by ShangBo on 2015-07-17
-- End
0 0
- Oracle 查询优化器 -- 访问路径
- 优化器访问路径的选择
- Oracle 配置查询优化器
- Oracle 查询优化器 -- 改写查询语句
- Oracle 访问路径
- Oracle 查询优化器 -- 表连接方法
- Oracle 学习:查询优化
- 分页查询优化--oracle
- oracle查询性能优化
- oracle 查询优化
- oracle查询优化
- Oracle 查询优化基本准则
- oracle查询语句优化
- Oracle数据库查询优化
- ORACLE 查询优化
- Oracle查询优化
- Oracle查询优化
- oracle查询优化
- Algorithms—142.Linked List Cycle II
- window7下的ElasticSearch的安装和学习(一)
- Linux系统下挂载windows(双系统)的NTFS文件系统
- 滴滴php面试总结
- POJ 2823 Sliding Window
- Oracle 查询优化器 -- 访问路径
- linux C进程信息查询
- Hadoop与传统数据仓库的区别
- Silverlight 应用程序中未处理的错误
- java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver+数据库连接的工具类
- CView Assert报错
- 希尔排序
- Apache CXF配置
- 认识3DMAX的各种插件