【问题标题】:Statistics not collected on Insert-Select未在 Insert-Select 上收集的统计信息
【发布时间】:2021-01-23 21:51:55
【问题描述】:

根据here 的信息,我希望在Oracle 中对新表执行Insert-Select 操作期间自动收集统计信息。但是,在插入-选择操作之后,我没有看到任何表级统计信息。

我已将参数 _optimizer_gather_stats_on_load 设置为 TRUE

根据要求(这只适用于新表),我创建了一个新表。插入选择之前没有行,插入选择操作后有 500 行。

我还有什么遗漏的吗?

更新: 这是我的数据库版本

select banner from v$version;
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

这是我正在创建的目标表:

create table test(id number, a number, b number);

这是我的插入语句:

insert /*+ APPEND */ into test select id, a, b from duptab;

这是我的参数值:

NAME                                   TYPE       VALUE
------------------------------------ ----------- -------
_optimizer_gather_stats_on_load      boolean     TRUE

仍然没有收集到统计数据:

SQL> select NUM_ROWS from user_tables where table_name = 'TEST';

  NUM_ROWS
----------

SQL> select log_mode from v$database;

LOG_MODE
------------
ARCHIVELOG

计划在这里

--------------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | INSERT STATEMENT      |        |    17 |   663 |     3   (0)| 00:00:01 |
|   1 |  LOAD AS SELECT       | TEST   |       |       |        |          |
|   2 |   MAT_VIEW ACCESS FULL| DUPTAB |    17 |   663 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

【问题讨论】:

  • 为了让测试用例完全可重现,你能不能用更简单的东西代替 DUPTAB,比如SELECT 1,1,1 FROM DUAL
  • 可能该功能被禁用,因为兼容性或优化器功能参数不标准。检查:select * from v$parameter where name in ('optimizer_features_enable', 'compatible');

标签: sql database oracle optimization


【解决方案1】:

首先检查您的数据库版本是否为 12g 或更高

然后查看此文档link

批量负载的在线统计数据收集

从 Oracle Database 12c 开始,数据库可以在以下类型的批量加载期间自动收集表统计信息:INSERT INTO ... SELECT 使用直接路径插入到空表中,以及 CREATE TABLE AS SELECT

因此,如果您没有看到收集到的统计信息,并且在 INSERT 之前表格是空的,您很可能

不要使用直接路径插入(见APPEND提示)

这里是一个简单数据的演示

select * from v$version;
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

创建表

create table tab as
select rownum id, 'xxx' pad 
from dual connect by level <= 10000;

select NUM_ROWS from user_tables where table_name = 'TAB';

  NUM_ROWS
----------
     10000
     

直接插入

drop table tab;
create table tab
(id number,
pad varchar2(10));


insert /*+ APPEND */ into tab
select rownum id, 'xxx' pad 
from dual connect by level <= 10000;
commit;

select NUM_ROWS from user_tables where table_name = 'TAB';

  NUM_ROWS
----------
     10000

插入

但正常插入不会产生统计信息!

drop table tab;
create table tab
(id number,
pad varchar2(10));


insert   into tab
select rownum id, 'xxx' pad 
from dual connect by level <= 10000;
commit;

select NUM_ROWS from user_tables where table_name = 'TAB';

  NUM_ROWS
---------- 

如果您认为应该进行自动收集但事实并非如此,请查看记录在案的限制 here

例如,如果表统计信息被锁定,则禁止收集

【讨论】:

  • 感谢您的回答。我尝试了 /*+ APPEND */ 提示,但仍然没有更新统计信息。
  • @Darzen APPEND 提示可能不起作用的原因有很多。您能否发布完整的INSERT 语句、表定义以及数据库是否处于归档日志模式?运行explain plan for insert ... 然后运行select * from table(dbms_xplan.display); 也可能会有所帮助 解释计划的注释部分有时会解释为什么不使用直接路径插入。
  • @Darzen 我添加了一个你可以重现的简单演示
  • 我已按照@JonHeller 的建议更新了更多信息
  • @Dazen 请检查here 聚会的限制。由于您的执行计划不包含操作OPTIMIZER STATISTICS GATHERING,我怀疑您的表统计信息已锁定。如果是,请解锁并重试,否则请检查记录的其他限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多