直方图
当某列数据分布不均衡。为了让CBO能生成最佳的运行计划,我们可能须要对表收集直方图,直方图最大的桶数(Bucket)是254。
收集直方图是一个很耗时的过程,如无必要。千万别去收集直方图。 Oracle的直方图有两种:
一种是频率直方图(FREQUENCY HISTOGRAM),当列中Distinct_keys 较少(小于254)。假设不手工指定直方图桶数(BUCKET),Oracle就会自己主动的创建频率直方图,而且桶数(BUCKET)等于Distinct_Keys。
一种是高度平衡直方图(HEIGHT BALANCED),当列中Distinct_keys大于254。假设不手工指定直方图桶数(BUCKET),Oracle就会自己主动的创建高度平衡直方图。 直方图用在什么情况下?
列的值分布很不均衡的时候,而且where条件中经经常使用到这个列。 直方图都准吗?
不一定。假设一个字段distinct值的个数许多,基本接近主键的distinct值的个数。就不是必需做直方图,直方图也不一定100%准确。 相关的@脚本在文章的最后面提供。 SQL> drop table a; 表已删除。 SQL> create table a as select * from dba_objects where rownum<=10000; 表已创建。 SQL> @anatab --常规的表分析
输入 ownname 的值: ggs
输入 tabname 的值: a
输入 estimate_percent 的值: 100
输入 skewonly_repeat_auto 的值: auto
输入 degree 的值: 4 PL/SQL 过程已成功完毕。 已用时间: 00: 00: 00.26
SQL> @getcolstat --字段的直方图
输入 owner 的值: ggs
输入 table_name 的值: a COLUMN_NAME NUM_ROWS CARDINALITY SELECTIVITY HISTOGRAM NUM_BUCKETS LAST_ANALYZED
---------------- ---------- ----------- ----------- --------------------- --------------
SECONDARY 10000 1 .01 NONE 1 28-7月 -14
GENERATED 10000 2 .02 NONE 1 28-7月 -14
TEMPORARY 10000 2 .02 NONE 1 28-7月 -14
STATUS 10000 1 .01 NONE 1 28-7月 -14
TIMESTAMP 10000 350 3.5 NONE 1 28-7月 -14
LAST_DDL_TIME 10000 385 3.85 NONE 1 28-7月 -14
CREATED 10000 303 3.03 NONE 1 28-7月 -14
OBJECT_TYPE 10000 34 .34 NONE 1 28-7月 -14
DATA_OBJECT_ID 10000 1836 18.36 NONE 1 28-7月 -14
OBJECT_ID 10000 10000 100 NONE 1 28-7月 -14
SUBOBJECT_NAME 10000 27 .27 NONE 1 28-7月 -14
OBJECT_NAME 10000 7725 77.25 NONE 1 28-7月 -14
OWNER 10000 9 .09 NONE 1 28-7月 -14 已选择13行。 SQL>
SQL> select object_type,count(*) from a group by object_type; OBJECT_TYPE COUNT(*)
------------------- ----------
INDEX 946
JOB CLASS 2
CONTEXT 2
TYPE BODY 82
PROCEDURE 50
RESOURCE PLAN 3
RULE 1
SCHEDULE 1
TABLE PARTITION 52
WINDOW 2
WINDOW GROUP 1
TABLE 841
TYPE 1088
VIEW 2953
LIBRARY 113
FUNCTION 68
TRIGGER 5
PROGRAM 3
CLUSTER 10
SYNONYM 2458
PACKAGE BODY 470
QUEUE 21
CONSUMER GROUP 5
EVALUATION CONTEXT 8
RULE SET 11
DIRECTORY 2
UNDEFINED 6
OPERATOR 15
SEQUENCE 102
LOB 128
PACKAGE 485
JOB 6
INDEX PARTITION 59
LOB PARTITION 1 已选择34行。 SQL> explain plan for select count(*) from a where object_type='INDEX'; 已解释。 SQL> @getplan
'general,outline,starts' Enter value for plan type:general PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 2223038180 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 25 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | TABLE ACCESS FULL| A | 294 | 2058 | 25 (0)| 00:00:01 | --跟实际不一致,上面查出来的是946
--------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("OBJECT_TYPE"='INDEX')
SQL> select 10000/34 from dual; --说明rows中的294是 估算值=总行数/字段distinct值的个数 10000/34
----------
294.117647 已选择 1 行。 SQL>
SQL> @anatab_col
输入 owner 的值: ggs
输入 table_name 的值: a
输入 columns 的值: object_type --做object_type字段的直方图 PL/SQL 过程已成功完毕。 SQL> explain plan for select count(*) from a where object_type='INDEX'; 已解释。 SQL> @getplan
'general,outline,starts' Enter value for plan type:general PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 2223038180 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 7 | 25 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 7 | | |
|* 2 | TABLE ACCESS FULL| A | 946 | 6622 | 25 (0)| 00:00:01 | --这里返回的是真实的行数,做object_type字段的直方图后,运行计划很准。 --------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("OBJECT_TYPE"='INDEX')
SQL>
SQL>
SQL>
SQL>
SQL> @getcolstat
输入 owner 的值: ggs
输入 table_name 的值: a COLUMN_NAME NUM_ROWS CARDINALITY SELECTIVITY HISTOGRAM NUM_BUCKETS LAST_ANALYZED
---------------- ---------- ----------- ----------- --------- ----------- --------------
SECONDARY 10000 1 .01 NONE 1 28-7月 -14
GENERATED 10000 2 .02 NONE 1 28-7月 -14
TEMPORARY 10000 2 .02 NONE 1 28-7月 -14
STATUS 10000 1 .01 NONE 1 28-7月 -14
TIMESTAMP 10000 350 3.5 NONE 1 28-7月 -14
LAST_DDL_TIME 10000 385 3.85 NONE 1 28-7月 -14
CREATED 10000 303 3.03 NONE 1 28-7月 -14
OBJECT_TYPE 10000 34 .34 FREQUENCY 34 28-7月 -14 --刚好等于distinct值
DATA_OBJECT_ID 10000 1836 18.36 NONE 1 28-7月 -14
OBJECT_ID 10000 10000 100 NONE 1 28-7月 -14
SUBOBJECT_NAME 10000 27 .27 NONE 1 28-7月 -14
OBJECT_NAME 10000 7725 77.25 NONE 1 28-7月 -14
OWNER 10000 9 .09 NONE 1 28-7月 -14 已选择13行。 SQL> select count(distinct object_name) from a; --总共才10000行,能够看出object_name的选择性是比較高的 COUNT(DISTINCTOBJECT_NAME)
--------------------------
7725 已选择 1 行。 SQL> @anatab_col
输入 owner 的值: ggs
输入 table_name 的值: a
输入 columns 的值: object_name PL/SQL 过程已成功完毕。 SQL> @getcolstat
输入 owner 的值: ggs
输入 table_name 的值: a COLUMN_NAME NUM_ROWS CARDINALITY SELECTIVITY HISTOGRAM NUM_BUCKETS LAST_ANALYZED
---------------- ---------- ----------- ----------- --------------- ----------- --------------
SECONDARY 10000 1 .01 NONE 1 28-7月 -14
GENERATED 10000 2 .02 NONE 1 28-7月 -14
TEMPORARY 10000 2 .02 NONE 1 28-7月 -14
STATUS 10000 1 .01 NONE 1 28-7月 -14
TIMESTAMP 10000 350 3.5 NONE 1 28-7月 -14
LAST_DDL_TIME 10000 385 3.85 NONE 1 28-7月 -14
CREATED 10000 303 3.03 NONE 1 28-7月 -14
OBJECT_TYPE 10000 34 .34 FREQUENCY 34 28-7月 -14
DATA_OBJECT_ID 10000 1836 18.36 NONE 1 28-7月 -14
OBJECT_ID 10000 10000 100 NONE 1 28-7月 -14
SUBOBJECT_NAME 10000 27 .27 NONE 1 28-7月 -14
OBJECT_NAME 10000 7725 77.25 HEIGHT BALANCED 75 28-7月 -14
OWNER 10000 9 .09 NONE 1 28-7月 -14 已选择13行。 SQL> select count(*) from a where object_name like '%A%'; COUNT(*)
----------
6404 已选择 1 行。 SQL> explain plan for select count(*) from a where object_name like '%A%'; 已解释。 SQL> @getplan
'general,outline,starts' Enter value for plan type:general PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------- Plan hash value: 2223038180 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 19 | 25 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 19 | | |
|* 2 | TABLE ACCESS FULL| A | 500 | 9500 | 25 (0)| 00:00:01 |
--------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("OBJECT_NAME" LIKE '%A%') --LIKE '%A%'对于cbo而言太复杂了。没有真正跑的话,cbo根本不知道真正返回多少行。
SQL> 已选择13行。 SQL> col OBJECT_NAME for a30
SQL> select OBJECT_NAME,count(*) from a group by OBJECT_NAME having count(*)>3 order by count(*) desc; OBJECT_NAME COUNT(*)
------------------------------ ----------
DBMS_REPCAT_AUTH 5 已选择 1 行。 SQL> explain plan for select count(*) from a where OBJECT_NAME='DBMS_REPCAT_AUTH'; 已解释。 SQL> @getplan
'general,outline,starts' Enter value for plan type:general PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------- Plan hash value: 2223038180 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 19 | 25 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 19 | | |
|* 2 | TABLE ACCESS FULL| A | 1 | 19 | 25 (0)| 00:00:01 |
--------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter("OBJECT_NAME"='DBMS_REPCAT_AUTH') --这个不复杂了吧,rows=1,一样不准。直方图也不可能保证100%准确的 所以说。并非全部字段都适合做直方图。 distinct值许多的,根本不适合做直方图。默认的桶数也装不下。
仅仅有字段值倾斜很严重,distinct值少,而且用到的sql中where条件包括了这个字段。假设sql中都没实用到这个字段,那也不是必需做直方图。
由于做直方图是很cpu性能的。 @脚本
--anatab.sql
set timing on
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => '&ownname',
tabname => '&tabname' ,
estimate_percent => &estimate_percent,
method_opt => 'for all columns size &skewonly_repeat_auto',
no_invalidate => FALSE,
degree => °ree,
cascade => TRUE);
END;
/
set timing off --anatab_col.sql
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => '&owner',
tabname => '&table_name',
estimate_percent => 100,
method_opt => 'for columns &columns ', --such as:col1,col2,col3...
no_invalidate => FALSE,
degree => 4,
granularity => 'ALL',
cascade => TRUE);
END;
/ --getcolstat.sql
col COLUMN_NAME for a30
select a.column_name,
b.num_rows,
a.num_distinct Cardinality,
round(a.num_distinct / b.num_rows * 100, 2) selectivity,
a.histogram,
a.num_buckets,
a.last_analyzed
from dba_tab_col_statistics a, dba_tables b
where a.owner = b.owner
and a.table_name = b.table_name
and a.owner = upper('&owner')
and a.table_name = upper('&table_name'); --getplan.sql
set feedback off
pro 'general,outline,starts'
pro
acc type prompt 'Enter value for plan type:' default 'general'
select * from table(dbms_xplan.display) where '&&type'='general';
select * from table(dbms_xplan.display(null, null,'advanced -projection')) where '&&type'='outline';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')) where '&&type'='starts';
set feedback on
undef type

oracle直方图的更多相关文章

  1. Oracle直方图的详细解析

    yuanwen:http://blog.csdn.net/javacoffe/article/details/5578206 Oracle直方图解析 一.    何谓直方图: 直方图是一种统计学上的工 ...

  2. Oracle 直方图理论

    一.何为直方图 直方图是一种几何形图表,它是根据从生产过程中收集来的质量数据分布情况,画成以组距为底边.以频数为高度的一系列连接起来的直方型矩形图,如图所示 二.ORACLE 直方图 在Oracle中 ...

  3. Oracle直方图的详细解析(转)

    Oracle直方图解析 一.    何谓直方图: 直方图是一种统计学上的工具,并非Oracle专有.通常用于对被管理对象的某个方面的质量情况进行管理,通常情况下它会表现为一种几何图形表,这个图形表是根 ...

  4. Oracle直方图导致SQL不走索引.

    在ITPUB 上看到一个帖子 http://www.itpub.net/thread-1875212-1-1.html 同一条SQL语句,只有查询条件不一样,查询返回的结果集都为0,一个走了全表扫描, ...

  5. Oracle 直方图实例测试

    --创建表 SQL> create table tab (a number, b number); Table created. --插入数据 SQL> begin .. loop ins ...

  6. ORACLE直方图(10g)

    为什么需要直方图 ?当表中一列数据比较的值分布比较均匀时,optimzer可以很好的通过最大值,最小值和NDV(唯一值的个数),就可以判断出cardinality.对于cardinality越精确,o ...

  7. oracle信息统计

    优化器统计范围: 表统计: --行数,块数,行平均长度:all_tables:NUM_ROWS,BLOCKS,AVG_ROW_LEN:列统计: --列中唯一值的数量(NDV),NULL值的数量,数据分 ...

  8. 收集oracle统计信息

    优化器统计范围: 表统计: --行数,块数,行平均长度:all_tables:NUM_ROWS,BLOCKS,AVG_ROW_LEN:列统计: --列中唯一值的数量(NDV),NULL值的数量,数据分 ...

  9. Oracle 课程七之分析和动态采样

    课程目标 完成本课程的学习后,您应该能够: •引子—统计信息的作用 •如何收集统计信息 •系统统计信息 •对象统计信息—表.字段.索引统计信息 •动态采样   统计信息的作用 Optimizer st ...

随机推荐

  1. C++之客户消费积分管理系统

    之前数据结构课程设计要求做这么一个小程序,现在贴上源码,来和大家进行交流学习,希望大家给出意见和建议 程序以链表为主要数据结构对客户信息进行存储,对身份证号码判断了位数及构成(前十七位为数字,最后一位 ...

  2. C++中bool类型变量初值对程序的影响

    很困惑的一个问题 #include<iostream> using namespace std; int main() { //bool a=true; //非0(1,2,3,……)输出1 ...

  3. Spark(一)Spark简介

    一.官网介绍 1 什么是Spark 官网地址:http://spark.apache.org/ Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎.Spark是UC Berkel ...

  4. 【LOJ】#2670. 「NOI2012」随机数生成器

    题解 矩阵乘法,注意需要快速乘 矩阵2*2 a c 0 1 代码 #include <iostream> #include <algorithm> #include <c ...

  5. 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式

    —————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流! —————————— GUI(Graphical User Interface)(图形用户接口):用图形 ...

  6. centos7 安装 supervisor

    一.安装 supervisor yum install python-setuptools easy_install supervisor 如果easy_install不好使就从官方下载: wget ...

  7. 【运维实战】一次linux日志分割之路——将日志按照每小时进行分割,并按照“日期-小时”格式保存

    是这样的,现在需要对nginx的access.log进行按照每小时进行分割,并且最好还要能够以 “日期+时间”的形式,命名保存. 两点,一个是按照每小时进行分割,一个是将日志以“日期+时间”的形式进行 ...

  8. Urllib库的基本用法

    1.什么是url? 统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址. 基本URL包含模式(或称协议).服务器名称(或IP地址).路径和文件名,如“ ...

  9. Java设计模式GOF之工厂模式

    一.工厂模式(Factory) 1.实现了创建者和调用者的分离 2.应用场景 ①JDK中 Calendar 的 getInstance(): ②JDBC 的 Connection 对象的获取: ③Hi ...

  10. BZOJ 2151 种树(循环链表)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2151 [题目大意] 在一个长度为n的数字环中挑选m个不相邻的数字使得其和最大 [题解] ...