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

在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 语句遇到上述情况,收集直方图信息是无效的。

参考文章:

oracle直方图解析

oracle 信息统计方法介绍

时间: 2024-08-04 08:57:14

【性能优化】执行计划与直方图的相关文章

11gr2全外连接优化执行计划(二)

在11.2中,Oracle对于全外连接的执行计划进行了优化. 这篇介绍新增的两个相关的HINT. 11gr2全外连接优化执行计划:http://yangtingkun.itpub.net/post/468/506826     Oracle在推出了新的执行计划的同时,还提供了两个控制这个执行计划的提示NATIVE_FULL_OUTER_JOIN和NO_NATIVE_FULL_OUTER_JOIN. 这两个HINT的使用十分简单,不需要其他的任何参数.下面继续上一篇文章的例子: SQL> SELE

11gr2全外连接优化执行计划(三)

在11.2中,Oracle对于全外连接的执行计划进行了优化. 这篇进一步介绍NATIVE_FULL_OUTER_JOIN提示. 11gr2全外连接优化执行计划:http://yangtingkun.itpub.net/post/468/506826 11gr2全外连接优化执行计划(二):http://yangtingkun.itpub.net/post/468/506876     虽然上一篇介绍了NATIVE_FULL_OUTER_JOIN和NO_NATIVE_FULL_OUTER_JOIN两

Oracle 11g r2全外连接优化执行计划(二) 新增的两个相关的HINT

Oracle在推出了新的执行计划的同时,还提供了两个控制这个执行计划的提示NATIVE_FULL_OUTER_JOIN和NO_NATIVE_FULL_OUTER_JOIN. 这两个HINT的使用十分简单,不需要其他的任何参数.下面继续上一篇文章的例子: SQL> SELECT /*+ NO_NATIVE_FULL_OUTER_JOIN */ T1.ID, T2.ID 2  FROM T1 FULL OUTER JOIN T2 3  ON T1.ID = T2.ID; ID        ID -

Oracle 11g r2全外连接优化执行计划(一)

在11.2中,Oracle对于全外连接的执行计划进行了优化. 在以前的版本中,全外连接的执行计划如下: SQL> SELECT * FROM V$VERSION; BANNER ---------------------------------------------------------------- Oracle Database10gEnterpriseEdition Release10.2.0.3.0 - 64bi PL/SQL Release 10.2.0.3.0 - Product

Oracle 11g r2全外连接优化执行计划(三)NATIVE_FULL_OUTER_JOIN提示

虽然上一篇介绍了NATIVE_FULL_OUTER_JOIN和NO_NATIVE_FULL_OUTER_JOIN两个HINT,但是实际上NATIVE_FULL_OUTER_JOIN并没有发挥任何的作用,因为Oracle对全外连接的优化使得新的执行计划的代价比原始执行计划要低,所以Oracle默认就选择这个执行计划,因此看不到NATIVE_FULL_OUTER_JOIN提示的效果. SQL> SET AUTOT ON SQL> SELECT T1.ID, T2.ID 2  FROM T1 FUL

MSSQL优化执行计划

今天来探索下MSSQL的执行计划,来让大家知道如何查看MSSQL的优化机制,以此来优化SQL查询.    代码如下 复制代码 --DROP TABLE T_UserInfo---------------------------------------------------- --建测试表 CREATE TABLE T_UserInfo (     Userid varchar(20),  UserName varchar(20),     RegTime datetime, Tel varch

11gr2全外连接优化执行计划

在11.2中,Oracle对于全外连接的执行计划进行了优化.     在以前的版本中,全外连接的执行计划如下: SQL> SELECT * FROM V$VERSION; BANNER----------------------------------------------------------------Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64biPL/SQL Release 10.2.0.3.0 - Pr

SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰

原文:SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰   本文出处:http://www.cnblogs.com/wy123/p/7190785.html  (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)   先抛出一个性能问题,前几天遇到一个生产环境性能极其低下的存储过程,开发人员根据具体的业务逻辑和返回的数据量,猜测到这个存储过程的执行应该不会有这么慢.当时意识到可能是执行计划缓存的问题,因为当

数据库访问性能优化_MsSql

在网上有很多文章介绍数据库优化知识,但是大部份文章只是对某个一个方面进行说明,而对于我们程序员来说这种介绍并不能很好的掌握优化知识,因为很多介绍只是对一些特定的场景优化的,所以反而有时会产生误导或让程序员感觉不明白其中的奥妙而对数据库优化感觉很神秘. 很多程序员总是问如何学习数据库优化,有没有好的教材之类的问题.在书店也看到了许多数据库优化的专业书籍,但是感觉更多是面向DBA或者是PL/SQL开发方面的知识,个人感觉不太适合普通程序员.而要想做到数据库优化的高手,不是花几周,几个月就能达到的,这