博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Oracle表访问调优——位图索引和单值查询
阅读量:4040 次
发布时间:2019-05-24

本文共 2682 字,大约阅读时间需要 8 分钟。

Oracle表访问调优——位图索引和单值查询

看下面一个示例:

在Oracle 自带的Sample Schema SH中,做一个单值查询后,获得如下的执行计划:

 

SELECT MAX(cust_credit_limit),

  COUNT(*)
FROM customers
WHERE cust_year_of_birth=1913;

 

 

确认CUSTOMERS表上的索引情况:

SELECT INDEX_NAME,

  INDEX_TYPE,
  TABLE_OWNER,
  TABLE_NAME,
  TABLE_TYPE
FROM user_indexes
WHERE table_name=upper('customers')
ORDER BY index_type ASC;

在CUSTOMERS表上有一个BITMAP类型的索引,名字是:CUSTOMERS_YOB_BIX

这个索引创建在COSTOMERS表的哪个列上呢?

可以通过下面的USER_IND_COLUMNS 视图获得表中列上的索引信息:

SQL> col index_name format a50;SQL> col table_name format a20;SQL> col column_name format a20;SQL> select index_name,table_name,column_name  2  from user_ind_columns  3  where table_name = upper('customers')  4  order by index_name asc;INDEX_NAME                                         TABLE_NAME           COLUMN_NAME-------------------------------------------------- -------------------- --------------------CUSTOMERS_GENDER_BIX                               CUSTOMERS            CUST_GENDERCUSTOMERS_MARITAL_BIX                              CUSTOMERS            CUST_MARITAL_STATUSCUSTOMERS_PK                                       CUSTOMERS            CUST_IDCUSTOMERS_YOB_BIX                                  CUSTOMERS            CUST_YEAR_OF_BIRTH

 

这样我们确认了在CUSTOMERS表的CUST_YEAR_BIRTH列上存在一个BITMAP类型的索引:CUSTOMERS_YOB_BIX

执行计划中的 BITMAP CONVERSION TO ROWIDS 和 BITMAP INDEX SINGLE VALUE 怎么解释?

BITMAP INDEX SINGLE VALUE 先通过键值筛选,然后BITMAP CONVERSION TO ROWIDS转换为rowid,再通过ROWID去回表TABLE ACCESS BY INDEX ROWID,这个过程和普通的索引扫描类似,只是多了一个BITMAP CONVERSION TO ROWIDS的操作。

因为存在位图索引,所以我们查询一下在CUSTOMERS表中CUST_YEAR_OF_BIRTH列上有多少个唯一值,通过下面的SQL语句实现:

SQL> SELECT num_distinct,  2    UTL_RAW.cast_to_number(low_value) low_value,  3    UTL_RAW.cast_to_number(high_value) high_value  4  FROM all_tab_col_statistics  5  WHERE table_name='CUSTOMERS'  6  AND column_name ='CUST_YEAR_OF_BIRTH';NUM_DISTINCT  LOW_VALUE HIGH_VALUE------------ ---------- ----------          75       1913       1990

 

在统计CUSTOMERS表一共有多少条记录?

SQL> select count(*) from customers; COUNT(*)----------     55500

我们可以看到CUSTOMERS表一共有 55500条记录,而CUST_YEAR_OF_BIRTH有75个不同的唯一值,那么每个值平均出现的次数为:55500 / 75 = 740 (条记录)。

而出生在 1913年的有 5条记录。

所以Oracle的查询优化器选择了使用索引来进行数据访问。这时正确的选择。

虽然不能为什么时候使用索引提供一个通用的规则,但是一般情况下,可以这样理解:

  • 如果需要访问表中所有或大部分记录,那么全表扫描是最快的方法;
  • 如果从大表中检索一条记录,那么基于该列的索引将提供更快的检索路径;
  • 在这两个极端之间,要预见哪种访问路径更快是很困难的。

Oracle的查询优化器如何在索引扫描和全表扫面之间选择?

影响优化器决策的因素如下:

  • 进行全表扫描徐璈读取的数据块数量;
  • 进行索引查询需要读取的数据块数量。这主要是基于对WHERE子句谓词返回的记录数目估计;
  • 进行全表扫描时多块读的相关开销,以及为满足索引查询进行的单块读的开销;
  • 内存中对缓存中的索引块和数据块数目的假设。

Oracle中访问数据的直方图统计,是一个非常有用的参考。

 

下面我们演示一种 “坏SQL” 的写法,故意绕过索引。

SELECT MAX(cust_credit_limit),  COUNT(*)FROM customersWHERE to_char(cust_year_of_birth)='1913';

这时,我们发现 产生了全表扫面的情况,即 TABLE ACCESS FULL。产生了大量的 physical reads。这时在查询中应该极力去避免的。

 

你可能感兴趣的文章
[leetcode BY python]1两数之和
查看>>
微信小程序开发全线记录
查看>>
PTA:一元多项式的加乘运算
查看>>
CCF 分蛋糕
查看>>
解决python2.7中UnicodeEncodeError
查看>>
小谈python 输出
查看>>
Django objects.all()、objects.get()与objects.filter()之间的区别介绍
查看>>
python:如何将excel文件转化成CSV格式
查看>>
机器学习实战之决策树(一)
查看>>
机器学习实战之决策树二
查看>>
[LeetCode By Python]7 Reverse Integer
查看>>
[leetCode By Python] 14. Longest Common Prefix
查看>>
[LeetCode By Python]118. Pascal's Triangle
查看>>
[LeetCode By Python]121. Best Time to Buy and Sell Stock
查看>>
[LeetCode By Python]122. Best Time to Buy and Sell Stock II
查看>>
[LeetCode By Python]125. Valid Palindrome
查看>>
[LeetCode By Python]136. Single Number
查看>>
[LeetCode By MYSQL] Combine Two Tables
查看>>
Android下调用收发短信邮件等(转载)
查看>>
Android中电池信息(Battery information)的取得
查看>>