【问题标题】:Identify a table with maximum rows in Oracle在 Oracle 中识别具有最大行数的表
【发布时间】:2016-09-27 19:33:02
【问题描述】:

我在 Oracle 中有一组表,我想确定包含最大行数的表。

因此,如果 A 有 200 行,B 有 345 行,C 有 120 行,我希望能够识别表 B。

我可以运行一个简单的查询来实现这一点吗?

编辑:有 100 多个表,所以我正在寻找通用的东西。

【问题讨论】:

  • 你为什么要检查这样的事情?所有表格都遵循相同的结构吗?
  • 不完全是。数据库的一部分遵循实体属性值模型 (EAV),我想确定分页是否合适。
  • 在这种情况下,也许您对表格占用的大小(即块数)比对行数更感兴趣。你可以从 user_tables 得到这个

标签: oracle plsql


【解决方案1】:

鉴于您说您使用的是 Oracle,我只想查询元数据。

select table_name, max(num_rows) from all_tables where table_name in ('A', 'B', 'C');

刚刚看到您的编辑。只需在没有 where 子句的情况下运行上面的代码,它将返回数据库中最大的表。唯一的问题可能是您可能会得到一个 SYS$ 表或其他东西。或者,如果您只是为了自己的知识而这样做,就这样做

select table_name, num_rows from all_tables order by num_rows; 

你会看到最大的是什么。

【讨论】:

  • 如果我没记错的话,ALL_TABLES 中的“num_rows”只是统计引擎计算的行数的估计
  • 我不认为这是一个“估计”,但它不是实时更新的,这是真的。 Preets 没有说这是为了什么,所以我假设她需要最简单的方法来交互地找到最大的桌子。我很想知道它是否适用于 Preets。
  • 谢谢你和丹!用 user_tables 执行它,它工作得很好!确实在寻找一种简单的方法来获得表中的最大行数。我需要它来确定用户是否希望在 GUI 上实现分页。如您所见,我对数据库管理知之甚少:)
  • 请注意,这只是一个近似值,Oracle 有时会收集统计信息,并且在此收集期间它会更新 num_rows。询问您的 DBA 是否以及何时收集统计信息。但是它很快,从 all_tables 中选择 num_rows 比从 > 中选择 count(*) 更快。
  • 您可以从 user_tables 判断它是否是估计值,以及分析该表的最后日期。警惕具有旧统计信息或没有统计信息的表。另一种方法是根据 user_segments 中的段大小进行估计——这不是行数,但至少它是正确的。
【解决方案2】:

架构中具有最大行数的表:

with data as 
(
 select table_name,
        to_number(extractvalue(xmltype(
                  dbms_xmlgen.getxml (
                 ' select count(*) c from ' || table_name)),
                  '/ROWSET/ROW/C')) countrows
 from   user_tables
)
select table_name, countrows
from   data 
where  countrows = (select max(countrows)
                    from   data);

dbms_xmlgen.getxml(' select .... ') 非常灵活。

【讨论】:

  • 这个语法很有趣!不会将它用于 this 特殊情况,但它似乎非常有用。
【解决方案3】:

这是另一种方法,它可能比简单地获取 ALL_TABLES.NUM_ROWS 慢得多,但它不依赖于已收集的统计数据并给出准确的当前值 - 尽管当前值取决于运行所需的时间!

-- For running in SQLPlus you need this to see the output.
-- If running in Toad or similar tool, output is enabled by default

    SET SERVEROUTPUT ON SIZE 100000

    DECLARE
      l_rows  INTEGER;
      l_max_rows  INTEGER := 0;
      l_table_name  all_tables.table_name%TYPE := NULL;
    BEGIN
      FOR table_record IN (SELECT table_name FROM all_tables) LOOP

        EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM '||table_record.table_name
          INTO l_rows;

        IF l_rows > l_max_rows THEN
          l_max_rows := l_rows;
          l_table_name := table_record.table_name;
        END IF;
      END LOOP;

      IF l_table_name IS NULL THEN
        dbms_output.put_line( 'All tables are empty' );
      ELSE
        dbms_output.put_line( 'Table ' || table_record.table_name || 
                              ' has ' || TO_CHAR(l_max_rows) || ' rows'
                            );
      END IF;
    END;
    /

【讨论】:

    【解决方案4】:
    select max(select count(*) from A union select count(*) from B...)
    

    应该可以。

    编辑:如果你想要动态的东西,你可以在 PL/SQL 中为每个“count(*)”子查询构建一个字符串(例如,列出来自 USER_TABLES 的表名),然后执行主查询:

    execute immediate 'select max('||subquery||')'
    

    【讨论】:

    • 我有很多桌子。我基本上想在完整的表格集上运行。我不想手动操作。
    • 这种技术不会指出哪个表的行数最多。
    • Ops,你是对的,它只会指示最大行数。但无论如何,我希望 OP 能找到一个好的算法......这并不难,看看我们的建议。
    【解决方案5】:

    您可以像这样通过一拖网获得相同的结果:

    SELECT     DISTINCT
               FIRST_VALUE ( t.owner )
                 OVER ( ORDER BY t.num_rows DESC NULLS LAST )
                                                     owner,
               FIRST_VALUE ( t.table_name )
                 OVER ( ORDER BY t.num_rows DESC NULLS LAST )
                                                     table_name,
               FIRST_VALUE ( t.num_rows )
                 OVER ( ORDER BY t.num_rows DESC NULLS LAST )
                                                     num_rows
    FROM       all_tables                            t
    

    【讨论】:

      【解决方案6】:

      David Aldridge 正确地指出,查询 all_tables 可能会由于缺少或陈旧的表统计信息而给出不正确的结果。但是使用user_segments也有问题;高水位线以下的已删除块仍将计入表格大小。

      例子:

      SQL>create table t as select * from all_objects
      
      Table created.
      
      SQL>select blocks, bytes from user_segments where segment_name = 'T';
      
          BLOCKS      BYTES
      ---------- ----------
             768    6291456
      
      SQL>delete from t
      
      52676 rows deleted.
      
      SQL>commit;
      
      Commit complete.
      
      SQL>select count(*) from t;
      
        COUNT(*)
      ----------
               0
      
      SQL>select blocks, bytes from user_segments where segment_name = 'T';
      
          BLOCKS      BYTES
      ---------- ----------
             768    6291456
      
      SQL>truncate table t;
      
      Table truncated.
      
      SQL>select blocks, bytes from user_segments where segment_name = 'T';
      
          BLOCKS      BYTES
      ---------- ----------
               8      65536
      

      【讨论】:

        【解决方案7】:

        这是一个获取数据库表中最大行数的查询..

        select table_name, num_rows from USER_TABLES
        where num_rows = (select  max(num_rows) from
        (select table_name, num_rows from USER_TABLES));
        

        【讨论】:

          猜你喜欢
          • 2017-06-07
          • 1970-01-01
          • 2020-05-24
          • 2021-11-26
          • 2021-05-19
          • 2021-05-18
          • 2011-09-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多