2

环境:Oracle数据库19C

有问题的表有几个数字数据类型列和一列 CLOB 数据类型。该表已正确编入索引,并且还有一个夜间收集统计工作。

以下是表上的操作-

  • PL/SQL 批处理过程从呈现为外部表的平面文件中插入 4 到 5 百万条记录
  • 在插入操作之后,另一个批处理读取行并更新一些列
  • 每日清除过程删除不再需要的行

我的问题是 - 是否应该在表上的插入和/或删除操作后立即触发收集统计信息?

根据此 Oracle 文档Online Statistics Gathering for Bulk Loads,批量加载仅在对象为空时自动收集在线统计信息。我的流程不会从中受益,因为当我加载数据时表不是空的。

但是在线统计数据收集适用于使用直接路径插入到空段上的选择操作中。所以接下来我将尝试附加提示。有什么想法吗... ?

4

1 回答 1

0

Before Oracle 12c, it was best practise to gather statistics immediately after a bulk load. However, according to Oracle's SQL Tuning Guide, many applications failed to do so, therefore they automated this for certain operations.

I would recommend to have a look at the dictionary views DBA_TAB_STATISTICS, DBA_IND_STATISTICS and DBA_TAB_MODIFICATIONS and see how your table behaves:

CREATE TABLE t AS SELECT * FROM all_objects;
CREATE INDEX i ON t(object_name);

SELECT table_name, num_rows, stale_stats
  FROM DBA_TAB_STATISTICS WHERE table_name='T'
UNION ALL
SELECT index_name, num_rows, stale_stats 
  FROM DBA_IND_STATISTICS WHERE table_name='T';

TABLE_NAME   NUM_ROWS   STALE_STATS
T               67135   NO
I               67135   NO 

If you insert data, the statistics are marked as stale:

INSERT INTO t SELECT * FROM all_objects;

TABLE_NAME   NUM_ROWS   STALE_STATS
T               67138   YES
I               67138   YES

SELECT inserts, updates, deletes 
  FROM DBA_TAB_MODIFICATIONS 
 WHERE table_name='T';

INSERTS UPDATES DELETES
  67140       0       0

Likewise for updates and delete:

UPDATE t SET object_id = - object_id WHERE object_type='TABLE';
4,449 rows updated.

DELETE FROM t WHERE object_type = 'SYNONYM';
23,120 rows deleted.

INSERTS UPDATES DELETES
  67140    4449   23120

When you gather statistics, stale_stats becomes 'NO' again, and `DBA_TAB_MODIFICATIONS* goes back to zero (or an empty row)

EXEC DBMS_STATS.GATHER_TABLE_STATS(NULL, 'T');

TABLE_NAME   NUM_ROWS   STALE_STATS
T              111158   YES
I              111158   YES

Please note, that `INSERT /*+ APPEND */ gathers only statistics if the table (or partition) is empty. The restriction is documented here.

So, I would recommend in your code, after the inserts, updates and deletes are done, to check if the table(s) appear in USER_TAB_MODIFICATIONS. If the statistics are stale, I'd gather statistics.

I would also look into partitioning. Check if you can insert, update and gather stats in a fresh new partition, which would be a bit faster. And check if you can purge your data by dropping a whole partition, which would be a lot faster.

于 2020-05-22T09:51:23.987 回答