web-dev-qa-db-ja.com

count(*)によるテーブルのOracle行カウントとDBA_TABLESからのNUM_ROWS

Count(*)はNUM_ROWSより遅いようです。この分野の専門家はこれにいくらか光を当てることができますか。

25

ドキュメント NUM​​_ROWSによると、 "テーブルの行数"であるため、これがどのように混乱するかがわかります。ただし、これら2つの方法には大きな違いがあります。

このクエリは、システムビューからMY_TABLEの行数を選択します。これは、Oracleが以前に収集して保存したデータです。

select num_rows from all_tables where table_name = 'MY_TABLE'

このクエリは、MY_TABLEの現在の行数をカウントします

select count(*) from my_table

定義により、それらは異なるデータです。 NUM_ROWSについて必要な追加情報が2つあります。

  1. ドキュメントには、列名のアスタリスクがあります。

    アスタリスク(*)でマークされた列は、ANALYZEステートメントまたはDBMS_STATSパッケージを使用してテーブルの統計を収集する場合にのみ入力されます。

    つまり、テーブルの統計を収集していない限り、この列にはデータがありません。

  2. デフォルトのestimate_percentで、または100%の見積もりで11g +で収集された統計は、その時点の正確な数値を返します。ただし、11gより前に収集された統計、または100%未満のカスタムestimate_percentを使用して収集された統計では、動的サンプリングが使用され、正しくない可能性があります。 99.999%を収集すると、1つの行が欠落する可能性があります。これは、得られる答えが間違っていることを意味します。

テーブルがnever更新されている場合、ALL_TABLES.NUM_ROWSを使用してテーブル内の行数を調べることは確かに可能です。 しかし、そしてそれは大きいですが、プロセスがテーブルから行を挿入または削除する場合、それはせいぜい良い近似であり、データベースに依存します統計を自動的に収集するのは恐ろしく間違っている可能性があります。

一般的に、システムテーブルに依存するよりも、テーブル内の行数を実際にカウントする方が常に優れています。

22
Ben