【性能优化】执行计划与直方图

简介:
在Oracle中直方图是一种对数据分布质量情况进行描述的工具。它会按照某一列不同值出现数量多少,以及出现的频率高低来绘制数据的分布情况,以便能够指导优化器根据数据的分布做出正确的选择。在某些情况下,表的列中的数值分布将会影响优化器使用索引还是执行全表扫描的决策。当 where 子句的值具有不成比例数量的数值时,将出现这种情况,使得全表扫描比索引访问的成本更低。这种情况下如果where 子句的过滤谓词列之上上有一个合理的正确的直方图,将会对优化器做出正确的选择发挥巨大的作用,使得SQL语句执行成本最低从而提升性能。
根据dba_objects创建一个倾斜列的表。并在严重倾斜的列上创建索引
YANG@yangdb-rac3> create table bind as select * from dba_objects;
Table created.
YANG@yangdb-rac3> update bind set status='INVALID' WHERE WNER='SCOTT';
6 rows updated.
YANG@yangdb-rac3> create index bind_idx on bind(status);
Index created.
收集表和索引的信息。
YANG@yangdb-rac3> exec dbms_stats.gather_table_stats(user,'BIND',cascade=>true);
PL/SQL procedure successfully completed.
YANG@yangdb-rac3> set autot trace exp
查看其执行计划,发现执行计划并没有走索引而是全表扫描
YANG@yangdb-rac3> select owner from bind where status='INVALID';
Execution Plan
----------------------------------------------------------
Plan hash value: 3586145581
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 36374 |   461K|   291   (1)| 00:00:04 |
|*  1 | TABLE ACCESS FULL| BIND | 36374 |   461K|   291   (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("STATUS"='INVALID')
为索引列的两个值创建直方图。
YANG@yangdb-rac3> EXEC DBMS_STATS.GATHER_TABLE_STATS(user,'BIND',method_opt => 'FOR ALL INDEXED COLUMNS  SIZE 2');
PL/SQL procedure successfully completed.
YANG@yangdb-rac3> select owner from bind where status='INVALID';
Execution Plan
----------------------------------------------------------
Plan hash value: 4106465825
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |    13 |   169 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| BIND     |    13 |   169 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | BIND_IDX |    13 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("STATUS"='INVALID')

但是当对于收集直方图的列在sql 语句where 中使用绑定变量的时候:执行计划改变了!没有选择索引而是全表扫描。
YANG@yangdb-rac3> variable val varchar2(10); 
YANG@yangdb-rac3> exec :val :='VALID';
PL/SQL procedure successfully completed.
YANG@yangdb-rac3> select owner from bind where status= :val;
Execution Plan
----------------------------------------------------------
Plan hash value: 3586145581
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 36374 |   461K|   291   (1)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| BIND | 36374 |   461K|   291   (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("STATUS"=:VAL)
YANG@yangdb-rac3> exec :val :='INVALID';
PL/SQL procedure successfully completed.
YANG@yangdb-rac3> 
YANG@yangdb-rac3> select owner from bind where status= :val;
Execution Plan
----------------------------------------------------------
Plan hash value: 3586145581
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 36374 |   461K|   291   (1)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| BIND | 36374 |   461K|   291   (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
--------------------------------------------------
   1 - filter("STATUS"=:VAL)
YANG@yangdb-rac3> alter system flush shared_pool;
System altered.
避免bind 变量,第一次执行时使用 INVALID 
YANG@yangdb-rac3> variable val varchar2(10);
YANG@yangdb-rac3> exec :val :='INVALID';
PL/SQL procedure successfully completed.
YANG@yangdb-rac3> select owner from bind where status= :val;
Execution Plan
----------------------------------------------------------
Plan hash value: 3586145581
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 36374 |   461K|   291   (1)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| BIND | 36374 |   461K|   291   (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("STATUS"=:VAL)
YANG@yangdb-rac3> select owner from bind where status= 'INVALID';
Execution Plan
----------------------------------------------------------
Plan hash value: 4106465825
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |    13 |   169 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| BIND     |    13 |   169 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | BIND_IDX |    13 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("STATUS"='INVALID')
其实直方图具有一下几个使用限制
1 all predicates on the column use bind variables 
2 the column data is uniformly distributed 
3 the column is not used in WHERE clauses of queries 
4 the column is unique and is used only with equality predicates 
当sql 语句遇到上述情况,收集直方图信息是无效的。
参考文章:
相关文章
|
SQL 存储 算法
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(二)|学习笔记
快速学习PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(二)
288 0
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(二)|学习笔记
|
存储 SQL JSON
MySql查询性能优化必知必会
作为一个写业务代码的 "JAVA CURD BOY" ,具备写出高效率SQL让应用高性能访问数据库的能力非常重要。获得这个能力的过程我收获了点知识和经验,今天在这里分享出来,希望大家多多交流指点。 本文内容主要包括以下几个方面:分析查询SQL,MySQL查询优化器、数据库存储结构、索引,索引维护,索引设计,SQL优化,表结构设计,分库分表,查询功能架构设计。
481 0
|
存储 SQL 缓存
MySQL查询性能优化(上)
MySQL查询性能优化(上)
212 0
MySQL查询性能优化(上)
|
SQL 存储 缓存
MySQL查询性能优化(下)
MySQL查询性能优化(下)
149 0
|
SQL 移动开发 关系型数据库
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
快速学习PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)
546 0
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
|
SQL XML JSON
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(一)|学习笔记
快速学习PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(一)
488 0
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(一)|学习笔记
|
存储 算法 关系型数据库
MySQL查询性能优化前,必须先掌握MySQL索引理论
数据库索引在平时的工作是必备的,怎么建索引,怎么使用索引,可以提高数据的查询效率。而且在面试过程,数据库的索引也是必问的知识点,
149 0
MySQL查询性能优化前,必须先掌握MySQL索引理论
|
SQL Oracle 关系型数据库
ORACLE实际执行计划与预估执行计划不一致性能优化案例
在一台ORACLE服务器上做巡检时,使用下面SQL找出DISK_READ最高的TOP SQL分析时,分析过程中,有一条SQL语句的一些反常现象,让人觉得很奇怪:   SELECT SQL_ID,        SQL_TEXT,        DISK_READS,        BUF...
1413 0
|
SQL 分布式计算 大数据
Spark SQL 性能优化再进一步:CBO 基于代价的优化
本文将介绍 CBO,它充分考虑了数据本身的特点(如大小、分布)以及操作算子的特点(中间结果集的分布及大小)及代价,从而更好的选择执行代价最小的物理执行计划,即 SparkPlan。