什么是谓词越界?谓词越界其实就是SQL语句的查询条件超出了数据库统计信息所记录的范围。谓词越界会导致Oracle优化器错误的选择SQL语句的执行计划,导致性能问题。

这里举一个简单的例子说明谓词越界导致优化器选择了错误的执行计划。

create table t1 (col1 number);
create index idx_t1 on t1(col1);beginfor i in 1..10000 loopinsert into t1 values (i);end loop;commit;
end;
/

这里创建了t1表,并在col1列上创建了索引,并向表里写入了10000条数据。提供过对t1表收集统计信息,可以得到目前表t1的谓词情况。

SQL> exec dbms_stats.gather_table_stats('SALP','T1');
SQL> select low_value,high_value from dba_tab_col_statistics where table_name='T1' and owner='SALP';LOW_VALUE  HIGH_VALUE
---------- ----------
C102       C302SQL> var x number;
SQL> exec dbms_stats.convert_raw_value('C102',:x);PL/SQL procedure successfully completed.SQL> select :x from dual;:X
----------1SQL> exec dbms_stats.convert_raw_value('C302',:x);PL/SQL procedure successfully completed.SQL> select :x from dual;:X
----------10000

上面用到了一个系统包,把统计信息表里的上下限裸数据转换成可读的数值。

在谓词范围内的条件查询的执行计划为

explain plan for select * from t1 where col1 between 1 and 10000;
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1387720244
-------------------------------------------------------------------------------
| Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |        | 10000 | 40000 |     7   (0)| 00:00:01 |
|*  1 |  INDEX FAST FULL SCAN| IDX_T1 | 10000 | 40000 |     7   (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------1 - filter("COL1">=1 AND "COL1"<=10000)
13 rows selected.

因为这里的条件包含了t1表内的所有数据,所以采用多块读且不需要回表的执行计划是最优的(table access full/index fast full scan),这里实际使用的是index fast full scan。

接下来继续向t1表写入数据

beginfor i in 10001..10000000 loopinsert into t1 values (i);end loop;commit;
end;
/

在不重新收集统计信息的情况下,检查表的统计信息

select low_value,high_value from dba_tab_col_statistics where table_name='T1' and owner='SALP';LOW_VALUE  HIGH_VALUE
---------- ----------
C102       C302

现在来进行一次谓词越界的查询,使用谓词条件 col1 between 10001 and 10000000。按道理来说,这种选择表里99.9%数据的语句应该使用多块读且不回表的执行计划(table access full/index fast full scan)。我们来实际试验一下。

SQL> set timing on;
SQL> Select count(*) from t1 where col1 between 10001 and 10000000;COUNT(*)
----------9990000Elapsed: 00:00:11.17
SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  86kr1tnhns36d, child number 0
-------------------------------------
Select count(*) from t1 where col1 between 10001 and 10000000Plan hash value: 1970818898----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |       |       |     2 (100)|          |
|   1 |  SORT AGGREGATE   |        |     1 |     4 |            |          |
|*  2 |   INDEX RANGE SCAN| IDX_T1 |     1 |     4 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------

可以看到这条语句执行了11s才出结果,且执行计划选择的是单块读的index range scan,而不是我们期望的多块读不回表的两种执行计划之一且返回的Rows和Bytes出现了严重预估错误。

我们重新为t1表收集一次统计信息,再次执行同样的语句并检查执行计划。

SQL> exec dbms_stats.gather_table_stats('SALP','T1');PL/SQL procedure successfully completed.
Elapsed: 00:00:07.92
SQL> select count(*) from t1 where col1 between 10001 and 10000000;COUNT(*)
----------9990000Elapsed: 00:00:00.31
SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  g47843nv7gsdq, child number 0
-------------------------------------
select count(*) from t1 where col1 between 10001 and 10000000Plan hash value: 3724264953---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |       |       |  4434 (100)|          |
|   1 |  SORT AGGREGATE    |      |     1 |     6 |            |          |
|*  2 |   TABLE ACCESS FULL| T1   |  9990K|    57M|  4434   (2)| 00:00:01 |
---------------------------------------------------------------------------

这次走出了我们希望的执行计划(table access full),预估的Rows和Bytes也都正常了,且语句花了310ms就运行完了。

谓词越界一般会发生在什么场景下?

1 临时表

这里指的是业务上的临时表而不是Oracle数据库本身的temporary table。在某些系统中会根据业务条件创建前台表和后台表,数据先进入前台表,处理完毕后,存入后台表,并用delete语句清理前台表的数据,前台表起到一个临时表的作用。我们知道,Oracle自动收集统计信息的默认时间窗口是工作日晚上的22点到凌晨2点,或者周末的早上6点到第二天凌晨2点。在自动收集统计信息窗口内,数据库前台表基本上处于无数据,或者数据量很小的情况,那么产生的统计信息就会和白天实际处理业务数据时有偏差,就有可能发生谓词越界的情况。

2 巨大表

Oracle触发自动收集某个表的统计信息的条件是表中修改的数据量超过该表数据总量的10%,假设一个表每天新增1w条数据,一年后这个表变成了365w条数据,那么这意味着这个表需要再过一个多月才会触发一次自动收集统计信息的作业。那么在这个表上的谓词查询,尤其是时间、序列等自增条件上的查询,就可能发生谓词越界的情况,影响优化器正确选择执行计划。

转载于:https://www.cnblogs.com/aegis1019/p/9059220.html

Oracle统计信息不准(谓词越界)造成的性能问题相关推荐

  1. [Oracle] oracle统计信息

    Oracle统计信息 Oracle数据库里的统计信息可以分为6种类型: 表的统计信息 索引的统计信息 列的统计信息 系统统计信息 数据字典统计信息 内部对象统计信息 图 1: Oracle统计信息 基 ...

  2. Oracle统计信息中的Pending Statistics

    点击上方"蓝字" 关注我们,享更多干货! 前言 Oracle中的统计信息相信大家都不陌生,统计信息中有Pending Statistics这个概念. 统计信息准确性对于CBO评估S ...

  3. 收集oracle统计信息

    原文地址为: 收集oracle统计信息 优化器统计范围: 表统计: --行数,块数,行平均长度:all_tables:NUM_ROWS,BLOCKS,AVG_ROW_LEN: 列统计: --列中唯一值 ...

  4. oracle统计信息

    oracle统计信息 study oracle基础  基础 统计信息相关 1.哪种优化器模式需要统计信息收集,ALL_ROWS 目前O3建议无论模式都进行统计信息收集,部分查询采取的是all_rows ...

  5. oracle收集统计信息和直方图,oracle统计信息和直方图

    oracle统计信息和直方图的理解[@more@]以前一直对统计信息的理解就是对行的数据分布的,提供改CBO来选择高效的执行计划.这段时间看了不少资料,对统计有了一个更清晰的认识 统计信息: 1,表中 ...

  6. oracle数据库直方图,[转] oracle统计信息(statistics)和直方图(histogram)

    oracle统计信息和直方图的理解 以前一直对统计信息的理解就是对行的数据分布的,提供改CBO来选择高效的执行计划.这段时间看了不少资料,对统计有了一个更清晰的认识 统计信息: 1,表中的统计信息 2 ...

  7. oracle统计信息被锁定处理

    oracle统计信息被锁定处理 基本现象 ORA-20005: object statistics are locked (stattype = ALL) 在进行SQL时,发现一个表的统计信息过旧,想 ...

  8. oracle 查看索引大小_技术分享|简述Oracle统计信息

    于树文 云技术管理处 在Oracle的11g版本中,统计信息为自动收集功能.在部署安装11g Oracle软件过程中,其中有一个步骤便是提示是否启动这个功能(默认是启用这个功能).有时候在生产环境中, ...

  9. 浅析Oracle统计信息

    oracle优化器(Optimizer) 优化器对于每一位从业人士都不陌生,它是oracle数据库内置的核心子系统,是数据库的核心,可以说优化器是数据库的一个灵魂,它在一定程度上决定了数据库的效率. ...

最新文章

  1. #串口通信超时处理_简单通信协议
  2. 破解网页禁止使用“复制”、“粘贴“
  3. 600度近视眼恢复方法_近视眼了怎么办?试试这几种方法,或许能奏效
  4. 安卓入门笔记之Activity
  5. Introspection
  6. 7.25第一次组队赛
  7. 【Elasticsearch】es Timelion是Kibana中时间序列的可视化工具
  8. 空字符python_Python中的None与 NULL(即空字符)的区别详解
  9. java 解析 datatabe,在JAVA实现DataTable对象(一)
  10. HDU4081 Qin Shi Huang's National Road System(次小生成树)
  11. Google广告优化与工具
  12. 南京邮电大学MOOC高级程序语言设计(C++)第六章编程题答案
  13. 如何用 matplotlib 画论文中的CNN结构图
  14. word页眉设置:显示章节标题、奇偶页不同
  15. C语言小项目实践——日历程序
  16. 身份证最后一位出现“X”之原因
  17. matlab验证线性卷积与圆周卷积的关系
  18. 网络爬虫---用urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化
  19. php表格所有边框实线,css表格怎么添加边框样式?css表格边框样式总结(附完整实例)...
  20. IntelliJ IDEA 项目中不小心把文件设置 Excluded 怎么恢复成原来的文件夹?

热门文章

  1. impala连接使用方法
  2. map和vector的迭代器失效问题(某公司招聘笔试试题)
  3. Eclipse 中 SDK无法更新---解决方法
  4. jsp+mysql+servlet的登录
  5. HDU 1251 统计难题 字典树/STL
  6. 软件工程——理论、方法与实践③
  7. eclipse怎么设置字体大小非原创
  8. Android: 启动另外的APP及传递参数(转)
  9. 基于visual Studio2013解决算法导论之007优先队列(堆实现)
  10. [转]NYOJ-511-移动小球