新特性概述
其实 oracle 的统计信息就是存储在数据字典里的一组数据,从多个维度描述了 oracle 数据库里对象的详细信息。 CBO 会利用这些统计信息来计算目标 SQL 各种可能的、不同的执行路径成本,并从中选择一条成本值最小的执行路径来作为目标 SQL 的执行计划,所以说收集统计信息对于数据库的 SQL 有着至关重要的作用! oracle 数据库会在一个固定的时间将数据库里的表和索引的相关统计信息进行收集。我们可以开启自动收集统计信息的功能也可以通过以下命令手动收集统计信息。
但是如今某些特定的生产数据库每日也存在频繁 DML 操作,为了给优化器提供准确的统计值,从而生成更加合理的执行计划。从 10g 的自动收集统计信息直到 19c 又推出了一个新的功能,实时收集数据对象的统计信息。 顾名思义实时收集就是只要发生 DML 操作以后, oracle 数据库就是立即开始收集统计信息。
需要格外注意的是,在 19c 中,这个特性只能在 Exadata 上使用,这个特性默认是启用的。如果没有 Exadata 环境,可通过设置参数 "_exadata_feature_on"=true 来模拟。请不要在非 Exadta 生产环境上使用
通过以下视图了解实时统计的信息
|
DBA_TAB_COL_STATISTICS |
此视图显示从 DBA_TAB_COLUMNS. 实时统计数据由 STATS_ON_CONVENTIONAL_DML 在 NOTES 列和 SHARED 在 SCOPE 列 |
|
DBA_TAB_STATISTICS |
此视图显示从 DBA_TAB_COLUMNS. 实时统计数据由 STATS_ON_CONVENTIONAL_DML 在 NOTES 列和 SHARED 在 SCOPE 列 |
查看统计信息
查看列级统计信息
SET PAGESIZE 5000 SET LINESIZE 200 COL COLUMN_NAME FORMAT a13 COL LOW_VALUE FORMAT a14 COL HIGH_VALUE FORMAT a14 COL NOTES FORMAT a5 COL PARTITION_NAME FORMAT a13 SELECT COLUMN_NAME, LOW_VALUE, HIGH_VALUE, SAMPLE_SIZE, NOTES FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME = 'SALES' ORDER BY 1, 5;
COLUMN_NAME LOW_VALUE HIGH_VALUE SAMPLE_SIZE NOTES AMOUNT_SOLD C10729 C2125349 5594 CHANNEL_ID C103 C10A 918843 CUST_ID C103 C30B0B 5595 PROD_ID C10E C20231 5593 PROMO_ID C122 C20A64 918843 QUANTITY_SOLD C102 C102 5593 TIME_ID 77C60101010101 78650C1F010101 5593
以上查询结果, NOTES 字段为空,则说明实时统计暂未收集
插入数据
尝试插入数据,看看实时统计是否执行
INSERT INTO sales(prod_id, cust_id, time_id, channel_id, promo_id, quantity_sold, amount_sold) SELECT prod_id, cust_id, time_id, channel_id, promo_id, quantity_sold * 2, amount_sold * 2 FROM sales; COMMIT;
从游标中获取执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format=>'TYPICAL'));
计划显示 LOAD TABLE CONVENTIONAL 在步骤 1 和 OPTIMIZER STATISTICS GATHERING 在步骤 2 中,这意味着数据库收集了实时统计在常规插入期间
再次查看列级统计信息
SET PAGESIZE 5000 SET LINESIZE 200 COL COLUMN_NAME FORMAT a30 COL LOW_VALUE FORMAT a30 COL HIGH_VALUE FORMAT a30 COL NOTES FORMAT a20 COL PARTITION_NAME FORMAT a30 SELECT COLUMN_NAME, LOW_VALUE, HIGH_VALUE, SAMPLE_SIZE, NOTES FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME = 'TEST' ORDER BY 1, 5;
SELECT COLUMN_NAME, LOW_VALUE, HIGH_VALUE, SAMPLE_SIZE, NOTES FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME = 'SALES' ORDER BY 1, 5; COLUMN_NAME LOW_VALUE HIGH_VALUE SAMPLE_SIZE NOTES ------------- -------------- -------------- ----------- ------------------------- AMOUNT_SOLD C10729 C224422D 9073 STATS_ON_CONVENTIONAL_DML AMOUNT_SOLD C10729 C2125349 5702 CHANNEL_ID C103 C10A 9073 STATS_ON_CONVENTIONAL_DML CHANNEL_ID C103 C10A 918843 CUST_ID C103 C30B0B 9073 STATS_ON_CONVENTIONAL_DML CUST_ID C103 C30B0B 5702 PROD_ID C10E C20231 9073 STATS_ON_CONVENTIONAL_DML PROD_ID C10E C20231 5701 PROMO_ID C122 C20A64 9073 STATS_ON_CONVENTIONAL_DML PROMO_ID C122 C20A64 918843 QUANTITY_SOLD C102 C103 9073 STATS_ON_CONVENTIONAL_DML QUANTITY_SOLD C102 C102 5701 TIME_ID 77C60101010101 78650C1F010101 9073 STATS_ON_CONVENTIONAL_DML TIME_ID 77C60101010101 78650C1F010101 5701
这时候我们发现 NOTES 字段显示 STATS_ON_CONVENTIONAL_DML ,则说明数据库在插入完数据以后,就实时收集了统计信息。
测试完毕, 19c 版本的数据库,开启实时统计功能后,在发生 DML 操作以后, oracle 数据库就会立即开始收集统计信息
