我们目前正在运行Oracle 11g,我正在研究是否需要在大量导入后运行统计信息。我们将statistics_level设置为' TYPICAL'。基于此,我认为我们不需要更新统计数据:
从Oracle Database 11g开始,MONITORING和NOMONITORING 已弃用关键字并收集统计信息 自动。
https://docs.oracle.com/cd/B28359_01/server.111/b28310/tables005.htm
然而,在创建我的数据库并运行我的适度导入(少数表中数百到数百万条记录以及创建多个索引)之后,受导入影响的所有表都显示为null对于last_analyzed和stale_stats使用下面的查询。
select
table_name,
stale_stats,
last_analyzed
from
dba_tab_statistics
where
owner = 'MY_SCHEMA'
order by
last_analyzed desc, table_name asc
;
我是否希望某些查询在此状态下效果不佳?
我是否应该期望最终运行统计数据并最终填充last_analyzed和stale_stats(文档表明这些值默认情况下每隔三小时更新一次)?
根据我的经验,对于中等大小的数据库(具有数百万条记录和少于10百万条记录的表格)来说,使用统计数据并不是必需的,并且通常会导致比解决的问题更多的问题。通常情况如此吗?
* * *关于我们的决议的说明* * *
我们正在使用这个:
analyze table my_table compute statistics
我们切换到了这个:
dbms_stats.gather_table_stats('MY_SCHEMA', 'MY_TABLE');
分析表语句在一个环境中大约需要1:30分钟,在第二个环境中大约需要15:00-20:00分钟。
在我们能够检查的两个实例中,gather_table_stats语句花了大约0:30到1:00分钟。
我们的计划是将分析表语句切换为gather_table_stats调用。
答案 0 :(得分:4)
STATISTICS_LEVEL和收集表/索引统计信息完全不同。如果在命令执行期间收集行源统计信息,则STATISTICS_LEVEL会生效。那么您就可以比较优化器估计值和显示光标中每个步骤的实际值。
因此,表/索引统计信息用于执行计划优化,STATISTICS_LEVEL用于在执行执行计划时收集执行统计信息,并且主要用于诊断目的。
当last_analyzed
为空时,表示尚未收集表统计信息。
stale_stats
表示统计数据是新鲜还是陈旧,或者下次是否会自动收集统计数据。默认设置为10%。如果您收集表统计信息,然后插入/更新/删除少于10%的行,则统计信息将被视为新的。当你达到修改行的10%时,它们就会变得陈旧。
默认情况下,Oracle会在维护窗口期间自动收集表/索引统计信息,这会在创建数据库时自动配置。如果有特定要求,它通常由DBA重新配置。
关于STATISTICS_LEVEL
,默认值为TYPICAL
,它看起来像这样:
HUSQVIK@hq_pdb_tcp> select * from dual;
D
-
X
HUSQVIK@hq_pdb_tcp> SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
SQL_ID a5ks9fhw2v9s1, child number 0
-------------------------------------
select * from dual
Plan hash value: 272002086
-------------------------------------------
| Id | Operation | Name | E-Rows |
-------------------------------------------
| 0 | SELECT STATEMENT | | |
| 1 | TABLE ACCESS FULL| DUAL | 1 |
-------------------------------------------
Note
-----
- Warning: basic plan statistics not available. These are only collected when:
* hint 'gather_plan_statistics' is used for the statement or
* parameter 'statistics_level' is set to 'ALL', at session or system level
我们看不到任何超过估计行数的内容。如果您设置ALTER SESSION SET statistics_level = ALL
,那么
HUSQVIK@hq_pdb_tcp> ALTER SESSION SET statistics_level = ALL;
HUSQVIK@hq_pdb_tcp> select * from dual;
D
-
X
HUSQVIK@hq_pdb_tcp> SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------
SQL_ID a5ks9fhw2v9s1, child number 1
-------------------------------------
select * from dual
Plan hash value: 272002086
------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | TABLE ACCESS FULL| DUAL | 1 | 1 | 1 |00:00:00.01 | 3 |
------------------------------------------------------------------------------------
现在我们还可以看到执行每个步骤所需的实际行数和时间以及一致读取次数(缓冲区列)。
使用更复杂的查询,您将获得比此更多的信息。您应该查看https://docs.oracle.com/database/121/ARPLS/d_xplan.htm
上的文档另请注意,统计信息采样不是每行都进行,但默认情况下每128行(可以使用未记录的_rowsource_statistics_sampfreq
参数进行更改)
答案 1 :(得分:1)
(Husqvik彻底解释了列和参数的含义,这个答案只涉及如何收集统计数据。)
在对表格进行重大 * 更改后,应手动收集统计信息。自11g以来,Oracle有一个很好的默认自动统计信息收集流程。但即使有了这个新系统,手动收集统计数据仍然至少有两个很好的理由。默认统计信息收集自动任务通常用于缓慢更改OLTP表,而不是快速更改的数据仓库表。
重大数据更改很容易导致严重的性能问题。如果要在加载后立即使用这些表,那么他们需要立即获得良好的统计信息。
ETL过程中的一个常见问题是表格从1行到100万行。优化器认为大型表中只有一行,并使用大量嵌套循环连接而不是散列连接。这些算法在不同的环境中运行良好;没有好的统计数据Oracle不知道正确的上下文。
值得注意的是,NULL LAST_ANALYZED
不是最糟糕的情况。当根本没有统计数据时,Oracle将使用动态采样来生成快速统计估计。最糟糕的情况是当桌子为空时,昨晚统计工作进行了。 Oracle认为它确实没有很好的统计数据。
统计信息自动任务可能无法跟上大的变化。统计信息auto-task是一个低优先级的单线程进程。如果自动流程中有太多大表,则可能无法在维护窗口期间处理它们。
坏消息是开发人员无法忽略优化程序统计信息。 DBA以后只能处理它。阅读手册中的一些章节可能会有所帮助,例如Managing Optimizer Statistics。
商品新闻是Oracle 11g最终有不错的默认设置。您通常不需要使用参数进行清理。在大多数情况下,遵循一条简单的规则:如果表格发生了显着变化,请运行:
dbms_stats.gather_table_stats('SCHEMA_NAME', 'TABLE_NAME');
*:"重要"是一个主观词。在相对大小方面,变化通常很重要,而非绝对变化。如果表当前有一行,则向表中添加一百万行是很重要的,但如果表有十亿行,则不是。