Oracleを含むほとんどのエンタープライズデータベースは、コストベースのオプティマイザを使用して、特定のSQLステートメントに適切なクエリプランを決定します。これは、オプティマイザーがデータに関する情報を使用して、ルールに依存するのではなく、クエリの実行方法を決定することを意味します(これは、古いルールベースのオプティマイザーが行ったことです)。
たとえば、単純なバグ追跡アプリケーションの表を想像してみてください
CREATE TABLE issues (
issue_id number primary key,
issue_text clob,
issue_status varchar2(10)
);
CREATE INDEX idx_issue_status
ON issues( issue_status );
私が大企業の場合、このテーブルには100万行ある可能性があります。これらのうち、100個にはissue_status
があります アクティブのうち、10,000はissue_status
を持っています のQUEUED、および989,900のステータスはCOMPLETEです。テーブルに対してクエリを実行して、アクティブな問題を見つけたい場合
SELECT *
FROM issues
WHERE issue_status = 'ACTIVE'
オプティマイザには選択肢があります。 issue_status
のインデックスを使用できます 次に、一致するインデックスの各行についてテーブルで単一行ルックアップを実行するか、issues
でテーブルスキャンを実行できます。 テーブル。どのプランがより効率的かは、テーブルにあるデータによって異なります。 Oracleがクエリがテーブル内のデータのごく一部を返すことを期待している場合は、インデックスを使用する方が効率的です。 Oracleがクエリがテーブル内のデータのかなりの部分を返すことを期待している場合、テーブルスキャンの方が効率的です。
DBMS_STATS.GATHER_TABLE_STATS
これは、Oracleがこの決定を行うことを可能にする統計を収集するものです。これは、テーブルに約100万行あり、issue_status
に3つの異なる値があることをOracleに通知します。 列、およびデータが不均一に分散されていること。したがって、Oracleは、クエリにインデックスを使用して、すべてのアクティブな問題を見つけることを知っています。しかし、振り返ってすべてのクローズされた問題を探しようとすると、それも知っています
SELECT *
FROM issues
WHERE issue_status = 'CLOSED'
テーブルスキャンを実行する方が効率的です。
統計を収集すると、データ量とデータ分布の変化に応じてクエリプランを時間の経過とともに変更できます。課題トラッカーを最初にインストールすると、完了した課題はほとんどなく、アクティブな課題とキューされた課題が増えます。時間の経過とともに、完了した問題の数ははるかに急速に増加します。テーブル内の行数が増え、さまざまなステータスにある行の相対的な割合が変わると、クエリプランが変更されるため、理想的な世界では、常に可能な限り最も効率的なプランを取得できます。