特定分区的 Oracle Gather_database_stats

问题描述 投票:0回答:1
select * from v$version
BANNER                                                                          
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0  Production  
TNS for IBM/AIX RISC System/6000: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

我希望使用 DBMS_STATS.GATHER_DATABASE_STATS 和 obj_filter_list 参数来收集特定表和分区的统计信息。 我意识到 Oracle 可以自动收集统计数据,这通常是最好/最有效的方法,但比我更聪明的人发现我们还需要添加此功能,以便我们在需要时集中/指定统计数据收集。 我遇到的问题是,如果我“只是”收集表上的统计信息(使用gather_database_stats),没有问题,dbms_stats.gather_database_stats 按预期完成其工作。但是,当我将分区名称添加到 obj_filter_list 时,不会收集统计信息。我只能假设我有点笨,要么我误解了这个过程,要么我做错了什么。

我正在使用的代码(实际上,过滤器列表的填充实际上将通过查询具有相关详细信息的表来完成)来尝试收集统计信息。:

declare
    filter_list dbms_stats.objecttab := dbms_stats.objecttab();
begin
    filter_list.extend(2);
    filter_list(1).ownname := 'USER01';
    filter_list(1).objname := 'TABLEABC';
    filter_list(1).objtype := 'TABLE';
    filter_list(1).partname := 'PART_CURR';
    
    filter_list(2).ownname := 'USER02';
    filter_list(2).objname := 'TAB_MYTAB';
    filter_list(2).objtype := 'TABLE';
    filter_list(2).partname := 'PART2023'    ;
    
    dbms_stats.gather_database_stats(obj_filter_list => filter_list);
end;
/

非常感谢任何见解。

oracle oracle11g
1个回答
0
投票

你的代码对我来说看起来是正确的,但我无法让它在 19c 上工作。不要调用 DBMS_STATS.GATHER_DATABASE_STATS 并使用参数 OBJ_FILTER_LIST,而是调用 DBMS_STATS.GATHER_TABLE_STATS 并使用参数 PARTNAME:

begin
    dbms_stats.gather_table_stats(ownname => user, tabname => 'TABLEABC', partname => 'PART_CURR');
end;
/

下面是一个基于您的代码的完全可重现的示例。它表明,尽管参数值看似正确,但 LAST_ANALYZED 字段均设置为 NULL,这意味着未收集任何统计信息。

-- drop table TABLEABC;
-- drop table TAB_MYTAB;

create table TABLEABC(a number, b number)
partition by list(a)
(
    partition p1 values (1),
    partition PART_CURR values(3)
);

create table TAB_MYTAB(a number, b number)
partition by list(a)
(
    partition p1 values (1),
    partition PART2023 values(3)
);

declare
    filter_list dbms_stats.objecttab := dbms_stats.objecttab();
    output_object_list dbms_stats.objecttab;
begin
    filter_list.extend(2);
    filter_list(1).ownname := user;
    filter_list(1).objname := 'TABLEABC';
    filter_list(1).objtype := 'TABLE';
    filter_list(1).partname := 'PART_CURR';

    filter_list(2).ownname := user;
    filter_list(2).objname := 'TAB_MYTAB';
    filter_list(2).objtype := 'TABLE';
    filter_list(2).partname := 'PART2023'    ;

    dbms_stats.gather_database_stats(obj_filter_list => filter_list, objlist => output_object_list);
end;
/

select last_analyzed from dba_tables where table_name in ('TABLEABC', 'TAB_MYTAB');
select last_analyzed, dba_tab_partitions.* from dba_tab_partitions where table_name in ('TABLEABC', 'TAB_MYTAB');

但是使用 PARTNAME 参数调用 DBMS_STATS.GATHER_TABLE_STATS 将正确设置 LAST_ANALYZED 值。

提到此过滤器参数的少数来源之一暗示存在一个错误,即过滤器列表仅在您还使用输出对象列表时才起作用。但是,即使我设置了该输出参数,该功能仍然无法工作。我什至在 Oracle 支持上找不到引用的错误号。

该功能似乎很少见且存在缺陷。即使您确实找到了某种方法使 OBJ_FILTER_LIST 起作用,您也应该避免它。

© www.soinside.com 2019 - 2024. All rights reserved.