day_of_week列を持つusersテーブルがあります。これはinteger(0 ... 6)です。毎日、スクリプトを実行して、その日のユーザーを反復処理する必要があります。
では、パフォーマンスを向上させるために、この列にインデックスを付ける必要がありますか?クエリは常に合計の1/7を返します。インデックスを追加すると、逆の効果が発生する可能性があります。usersテーブルの10k〜100k行を想像してみてください。
ちなみに、重要な場合はPostgreSQLを使用しています。
day_of_week列を持つusersテーブルがあります。これはinteger(0 ... 6)です。毎日、スクリプトを実行して、その日のユーザーを反復処理する必要があります。
では、パフォーマンスを向上させるために、この列にインデックスを付ける必要がありますか?クエリは常に合計の1/7を返します。インデックスを追加すると、逆の効果が発生する可能性があります。usersテーブルの10k〜100k行を想像してみてください。
ちなみに、重要な場合はPostgreSQLを使用しています。
いいえ。カーディナリティが非常に低いため、直接テーブルスキャンの方が安価であるため、インデックスを作成しないでください。結果セットをその上でソートする必要がある場合にのみ価値があります。しかし、それは他の要因に依存します。
テーブルの全行の数パーセントを超える値が存在する場合、その値をフィルタリングするクエリは、インデックスでそれらを見つけた後、テーブルのほとんどのページにアクセスする必要があります。したがって、最初にインデックスを検索しても意味がありません。これは単なる二重の作業です。
一般的な経験則として、クエリがテーブルの約5%を超えてプルする場合、インデックス付けはあまり意味がありません。ただし、テーブルのプロパティによっては、他にも調べる必要があります。たとえば、Postgresで、パーティショニングを見てください。
パーティショニングとは、論理的に1つの大きなテーブルを小さな物理的な部分に分割することです。パーティショニングにはいくつかの利点があります。
クエリのパフォーマンスは、特定の状況で劇的に向上する可能性があります。特に、テーブルの頻繁にアクセスされる行のほとんどが単一のパーティションまたは少数のパーティションにある場合です。パーティション化は、インデックスの先頭の列の代わりになり、インデックスサイズを縮小し、インデックスの頻繁に使用される部分がメモリに収まる可能性を高めます。
クエリまたは更新が単一のパーティションの大部分にアクセスする場合、テーブル全体に散在するインデックスとランダムアクセス読み取りを使用する代わりに、そのパーティションのシーケンシャルスキャンを利用することで、パフォーマンスを向上させることができます。
一括ロードと削除は、パーティションの設計でその要件が計画されている場合は、パーティションを追加または削除することで実行できます。ALTER TABLE NOINHERITとDROPTABLEは、どちらも一括操作よりもはるかに高速です。これらのコマンドは、一括DELETEによって発生するVACUUMオーバーヘッドも完全に回避します。
めったに使用されないデータは、より安価で低速のストレージメディアに移行できます。
または、データが更新されることはなく、追加を挿入するだけだと言います。ビットマップインデックスのようなものが理にかなっている可能性があります。