私たちは、データベースに一定期間の間のみ関連性のある/有効なテーブルをたくさん用意しています。契約の例として、start_dateとend_dateがあります。そして、それは必ずしも完全な月ではありません。タイムスライスを見つけるためにデータ/インデックスをモデル化する方法
さて、これは、このテーブルに対するクエリの典型的なタイプです:
SELECT
*
FROM
contracts c
WHERE
c.start_date <= :1
AND c.end_date >= :2
AND c.region_id = :3
私たちは、テーブル内のデータの20年(〜7000日)を持っているので、日付が場合は特に、非常に優れたフィルタ基準であります: 1と:2は同じ日です。 region_idはあまり良いフィルタ基準ではありません(〜50)。オプティマイザは、それが安いだと思っているため残念ながら
contracts_valid_index (start_date, end_date)
contracts_region (region_id)
、クエリ以上になることが多い私たちcontracts_regionインデックス:この例では、(特に)私たちのテーブルの上に2つのインデックスを持っています。これは、データの途中で1日を選択すると、データの半分だけをフィルタリングするため、start_dateのインデックスは実際にはうまくいかないとデータベースは考えます。 end_dateを見ることで同じことが言えます。したがって、オプティマイザは自分のデータの1/4だけをフィルタリングできると考えています。なぜなら、彼はstart_dateとend_dateが通常はかなり接近していることを知らないので、このインデックスは非常に選択的です。
contracts_valid_indexを使用する実行計画の方が、contracts_regionを使用する実行計画よりもコストが高くなります。しかし、実際にはcontracts_valid_indexはずっと優れています。
私は現在、よりよいインデックスを作成してクエリを高速化できるとは思わない(contracts_valid_index以外のすべてを削除する以外に)。しかし、おそらく私のデータモデルはクエリオプティマイザにとってあまり良くありません。だから私は、他の人たちも同様のニーズを抱えていて、データのモデル化やデータテーブル/インデックスの最適化方法を知りたいと思っています。
提案がありますか?
これは私が探していたものです。私はインターバルの終わりが気に入らないが、それは問題ではない。しかし、私はこれについてJPAのサポートを受けるつもりはない – EasterBunnyBugSmasher
これを投稿した後にもう少しリサーチを行ったところ、開始日と終了日の列は日付またはタイムスタンプのいずれかになり、NULL値は時間の始めと終わりとして扱われますそれらの値にマジックの日付を使用すると、彼らは引き続き動作します。 – Sentinel
オープンとクローズド・エンドの範囲に関しては、私は両方で働いてきており、オープン・エンドの方がはるかに優れています。そのようにして1つの範囲が終わり、次の範囲が始まると、次の開始と同じようにプリオーダーの終わりに同じ日付を使うことができ、重なりの心配はありません。開始日と終了日に切り捨てられた値を使用している場合、1つの範囲の終了と次の開始の間のギャップに収まる範囲外の範囲チェックを心配する必要はありません。 – Sentinel