1

私は2つのテーブルを持っています:

  • トリップ:id_trip、id_object、trip_date、delta(8980026行)
  • 範囲:id_range、id_object、date_since、date_until(18490行)

次のselectステートメントを最適化する必要があります

  select r.id_range, sum(t.delta) sum_deltas
    from trips t,
         ranges r
   where t.id_object = r.id_object
     and t.trip_date between r.date_since and r.date_until
group by r.id_range

条件に応じて、「範囲」内のトリップに一致する行が常に1つだけ存在します。

  • トリップテーブルは常に増え続けていますが、更新や削除はありません
  • テーブルの範囲は、任意の方法(削除、更新、挿入)で時々変更される可能性があるため、関数ベースのインデックスは方法ではありません:(
  • id_object(両方のテーブル)とdate_since(トリップ)にインデックスがあります

誰かが物事をスピードアップする方法を知っていますか、それも可能ですか?

4

2 に答える 2

1

データのセグメンテーション(つまり、データを特定の日付で分割し、クエリが適切なパーティションにのみヒットするようにする)とインデックスを確認することをお勧めします。これらにより、クエリプロセスが高速化される可能性があります。

また、データウェアハウスを検討することもできます... Tripsは更新または削除されないため、レポートの生成やアドホッククエリにより適したデータ構造への非正規化の理想的な候補です。

于 2012-06-06T08:59:14.603 に答える
1

物事をスピードアップすることは常に可能です。時間/労力/お金/ディスクスペース/追加のオーバーヘッドなどの価値がない場合があります。

まず、明示的な結合構文を使用してください。これは数十年前からSQL標準であり、多くの潜在的なエラーを回避するのに役立ちます。クエリは次のようになります。

select r.id_range, sum(t.delta) sum_deltas
  from trips t
  join ranges r
    on t.id_object = r.id_object
   and t.trip_date between r.date_since and r.date_until
 group by r.id_range

このクエリは、2つのインデックスが必要であることを意味します-可能であれば一意です。にインデックスrangesが必要ですid_object, date_since, date_until。のインデックスはにtripsなりますid_object, trip_date。小さければ、そのインデックスの最後にtrips追加することを検討するかもしれませんdelta。そうすれば、テーブルにまったく入らず、インデックススキャンのみを実行できます。現状では、インデックスROWIDによるテーブルアクセスを実行する必要があります。

あなたの問題が少し異なるかもしれないことをすべて書いた。このクエリを使用して、両方のテーブルをフルスキャンします。問題はインデックスである可能性があります。オプティマイザがインデックスを使用している場合は、インデックスにない列を使用しているため、インデックスのROWIDによるテーブルアクセスを実行するため、id_objectまたはtripsのそれぞれに対してインデックスの一意/範囲スキャンを実行している可能性があります。rangesこれは非常に高額になる可能性があります。

ヒントを追加して、両方のテーブルのフルスキャンを強制してみてください。

select /*+ full(t) full(r) */ r.id_range, sum(t.delta) sum_deltas
  from trips t
  join ranges r
    on t.id_object = r.id_object
   and t.trip_date between r.date_since and r.date_until
 group by r.id_range
于 2012-06-06T09:27:03.963 に答える