web-dev-qa-db-ja.com

すべての値が36文字の場合、charとvarcharのほうがインデックス検索が著しく高速になります

すべてのテーブルの主キーにハッシュベースの生成されたIDを使用するレガシースキーマ(免責事項!)があります(多数あります)。そのようなIDの例は次のとおりです。

_922475bb-ad93-43ee-9487-d2671b886479
_

このアプローチを変更する可能性はありませんが、インデックスアクセスのパフォーマンスは低下します。これが考えられる無数の理由は別として、最適とは言えないことに気づいたことが1つあります。多くのすべてのテーブルのすべてのID値の長さが正確に36文字であるにもかかわらず、列の型はvarchar(36)、-です。 notchar(36)

列タイプを固定長に変更することはできますかchar(36)は、インデックスページごとのエントリ数のごくわずかな増加を超えて、任意の有意インデックスパフォーマンスの利点を提供しますか?

つまり、可変長型よりも固定長型を扱う方が、postgresのパフォーマンスがはるかに速くなりますか?

最小限のストレージ節約については触れないでください-カラムを変更するために必要な手術と比較してもそれは問題ではありません。

33
Bohemian

いいえまったく利益がありませんマニュアルには明示的に記載されています

ヒント:これら3つのタイプの間にパフォーマンスの違いはありませんが、空白で埋められたタイプを使用した場合のストレージスペースの増加、および長さ制約のある列に格納するときに長さを確認してください。 character(n)は他の一部のデータベースシステムではパフォーマンスの利点がありますが、PostgreSQLにはそのような利点はありません。実際、character(n)は追加のストレージコストのため、通常3つのうちで最も遅くなります。 ほとんどの場合、代わりにtextまたはcharacter varyingを使用する必要があります

大胆な強調鉱山。

char(n)は、主に古い、役に立たないタイプです。 varchar(n)のままにします。最大長を強制する必要がない場合、varcharまたはtextは少し高速です。 (違いを測定することはできません。)

すべての文字列の長さが正確に36文字である場合、noストレージがいずれかの方法で保存され、非常に小さいものでもありません。どちらもディスク上とRAM内でまったく同じサイズです。 pg_column_size() でテストできます(式およびテーブル列で)。

そして、すべての文字列が36文字である必要がある場合は、CHECK (length(col) = 36)制約を適用してtextにし、exact長さ。varchar(36)ではなく、最大値のみを適用します。長さ。

関連:

あなたは他のオプションを求めませんでしたが、私は2つ言及します:

  1. COLLATION - "C"照合順序でDBを実行している場合を除く =。照合順序は見落とされがちで、おそらく高価です。あなたの文字列は自然言語では意味がないように見えるので、COLLATIONの規則に従うことはおそらく意味がありません。関連:

    (特に)パフォーマンスに対するCOLLATE "C"の影響を比較する広範なベンチマーク:

  2. [〜#〜] uuid [〜#〜] 、明らかに。文字列は疑わしいUUID(32桁の16進数と4つの区切り文字)のように見えます。これらを実際のuuidデータ型として保存する方がはるかに効率的です。これは、複数の方法でより高速で、16バイトしか占有しません- 37バイトRAM for char(36)またはvarchar(36)(区切り文字なしで保存され、32定義文字のみ)、または33バイトがディスクに保存されます。ただし、 alignment padding40多くの場合、どちらの方法でもバイトです。)COLLATIONは、uuidデータ型にも無関係です。

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid
    

    これは役立つかもしれません(最後の章):

    以下も参照してください。

44