Return 计数值为 0 的 table_name 和 partition_name

Return the table_name and partition_name whose count have a value of 0

我正在尝试编写一个查询,其中 return table_name 和 partition_name 的分区计数值为 0。

我得到以下查询 return 表的 SELECT COUNT() 及其分区:

SELECT 'SELECT COUNT(*) FROM ' || TABLE_NAME || ' PARTITION (' || PARTITION_NAME || ');'
FROM user_tab_partitions
ORDER BY table_name;

这些 SELECT return:

SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201210);
SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201104);
SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201301);

最后一个是唯一的return数据:

COUNT(*) |
2430276  |

我需要的是return那些table_name和partition_name没有数据的查询。像这样:

TABLE_NAME | PARTITION_NAME
A5109713   | PT5109713_201210
A5109713   | PT5109713_201104

这种使用动态 SQL 的方法实施起来很重,执行起来也很慢(因为您需要手动计算每个分区中的行数)。此外,您现在发现自己需要一些额外的逻辑,这将需要更多 PL/SQL 代码。

系统视图 user_tab_partitions 具有名为 num_rows 的列,即 documented as分区中的行数 。它包含的信息的可靠性取决于您的统计数据的新鲜度。

因此,如果您的统计信息是最新的,那么您可以直接从视图中获取您正在寻找的信息:

select table_name, partition_name
from user_tab_partitions
where num_rows = 0
order by table_name, partition_name

我想要这样的程序:

DECLARE
    r INTEGER;
    cur sys_refcursor;
BEGIN
    FOR aPart IN (SELECT TABLE_NAME, PARTITION_NAME FROM USER_TAB_PARTITIONS ORDER BY TABLE_NAME, PARTITION_POSITION) LOOP
        OPEN cur FOR 'SELECT ROWNUM FROM '||aPart.TABLE_NAME||' PARTITION ('||aPart.PARTITION_NAME||') WHERE ROWNUM <= 1';
        FETCH cur INTO r;
        IF cur%NOTFOUND THEN
            DBMS_OUTPUT.PUT_LINE(aPart.TABLE_NAME||CHR(9)||aPart.PARTITION_NAME);
        end if;
        close cur;
    END LOOP;
END;

我不会依赖 NUM_ROWS 的看法 USER_TAB_PARTITIONS 因为它包含的信息的可靠性取决于您的统计数据的新鲜度。

出于性能原因,我使用 SELECT ROWNUM FROM ... WHERE ROWNUM <= 1; 而不是 COUNT(*)。其实你对总行数不感兴趣,你只想知道它们是否大于0。

在最坏的情况下 COUNT(*) 运行 FULL-TABLE 扫描,这比只读取第一条记录要慢得多。