TL;DR バージョン: これについて心配するのは、おそらく時間の無駄です。
長いバージョン:
Postgres には列挙型があります。
create type myenum as enum('foo', 'bar');
varchar または整数フィールドと比較して、長所と短所があります。主にプロの私見。
サイズ的には、 として保存されるoid
ので、int32
タイプです。これにより、典型的な値 (たとえば'draft'
、'published'
、'pending'
、'completed'
、列挙型が何であれ) が入力された varchar よりも小さくなり、int
型と同じサイズになります。値が非常に少ない場合、smallint
/int16
は確かに小さくなります。パフォーマンスの変化の一部はそこから生じます (フィールドが小さい場合と大きい場合、つまり、ほとんど無視できます)。
のビルトイン カタログ ルックアップenum
、チェック制約、 または の外部キーなど、varchar
いずれの場合も検証が可能int
です。パフォーマンスの変化の一部はそこからもたらされますが、おそらく時間の価値もありません.
列挙型のもう 1 つの利点は、順序付けられることです。上記の例では'foo'::myenum < 'bar'::myenum'
、 が可能になりorder by enumcol
ます。varchar
またはを使用して同じことを達成するにはint
、列または何かを含む別のテーブルが必要になりますsortidx
...この場合、列挙型の値で並べ替えたい場合、列挙型は大きな利点をもたらす可能性があります。これは、列挙型がカタログにどのように格納されるかに関連する唯一の落とし穴に私たちをもたらします...
内部的には、各列挙型の値にはが含まoid
れ、後者はテーブル内にそのまま格納されます。したがって、技術的にはint32です。列挙型を作成すると、その値が正しい順序でカタログ内に格納されます。上記の例で'foo'
は、oid
より低い'bar'
. これにより、値のソートに相当するため、Postgres が enum の値で順序付けすることが非常に効率的になりint32
ます。
ALTER
ただし、列挙型の場合、その順序を変更する状況に陥る可能性があります。たとえば、上記の列挙型をmyenum
nowのように変更したとします('foo', 'baz', 'bar')
。効率性に関連する理由から、Postgres はoid
既存の値に新しい値を割り当てたり、それらを使用するテーブルを書き換えたり、それらを使用するキャッシュされたクエリ プランを無効にしたりすることはありません。代わりに、 に別のフィールドを入力してpg_catalog
、正しい並べ替え順序が得られるようにします。sortidx
その時点から、enum フィールドによる順序付けには追加のルックアップが必要になります。これは、事実上、テーブルをフィールドを持つ別の値テーブルと結合するvarchar
ことint
になります。 .
これは通常問題なく、完全に受け入れられます。時々、そうではありません。解決策がない場合は、列挙型でテーブルを変更し、それらの値を varchar に変更します。また、それを利用する機能とトリガーを見つけて調整します。次に、タイプを完全に削除してから、再作成して新しい oid 値を取得します。最後に、テーブルを元の場所に戻し、関数とトリガーを再調整します。些細なことではありませんが、確かに実現可能です。