web-dev-qa-db-ja.com

VARCHAR主キー-MySQL

現在、2列のcategoriesテーブルがあります-category VARCHAR(50) NOT NULL PRIMARY KEYparent VARCHAR(50)parent列は、category列への外部キー(FK)です。

これは最も明白なアプローチのようです。ただし、主キーにVARCHAR列を使用しているため、アラームベルが頭の中で鳴っています。これにより、テーブルを照会するときの操作が遅くなる可能性があります。

cat_id INT AUTO_INCREMENTという3番目の列を導入してPKに設定することもできますが、意味のない新しい列が導入されます。

どちらが高速になるかとは別に、他にどのような考慮事項を検討する必要がありますか?

最大で1000カテゴリ程度になると予測しているため、行数はそれほど多くありません。ただし、categories PK列は、他のテーブルの多くの外部キーの参照列になります。

PKとして(一意の)ユーザー名を使用する必要がありますか?

7
dayuloli

主キーとしてのVARCHAR列は、通常同じ列にクラスターインデックスを作成するため、適切な選択ではありません。

VARCHAR列のクラスターインデックスは、断片化率が高いことが予想されるため、不適切な選択です。新しく挿入されるすべてのキー値は、既存のキーの間のどこかでその場所を見つけようとし、通常はページ分割と高インデックスの断片化を引き起こします。その結果、パフォーマンスが低下し、追加のインデックスの再構築/再編成コストが発生します。

次に、varcharキー列を外部キーとして使用すると、疑似キーauto-incremented列と比較して余分なスペースが必要になります。

だが

自動インクリメントされた列のクラスター化インデックスは、「ホットスポット」を作成する場合があります。これを注意深く読んでください 「インクリメントキーに基づいてクラスタ化インデックスを作成しないでください」というSQL Server 2000日の神話はありますか?

ホットスポットが問題になる可能性がありますが、多くのユーザーが値を挿入しようとしていますが、あなたの場合はvarcharと比較して自動インクリメントされた列に移動したいと思います。

8
aasim.abdullah

はい、代理の4バイト整数キーを追加します。現在の2つの列は100バイトですが、新しいID列を追加することで、これを58バイトに減らすことができます。 65,535のカテゴリを超えないことが確実な場合は、サロゲートキーを2バイトのsmallintにすることもできます(念のためINTのままにしておくことをお勧めします)。

スペースの節約は、1,000行のテーブルの場合はそれほど大きくありませんが、cat_idを他のテーブルに追加すると、大幅なスペース(FKごとに50バイトではなく4バイト)を節約できます。また、おそらくこれらの外部キーにインデックスを付けることもできます。そのため、すべての非クラスター化インデックスでもスペースの節約がさらに大きくなります。

また、クラスター化インデックスは順次になり、新しいカテゴリを追加する際の断片化(ページ分割)を回避します

テーブル構造:-

create table dbo.Cateogory (
    CateogoryID int not null identity(1,1) constraint pkCateogory primary key clustered,
    Cateogory varchar(50) not null constraint ukCateogory unique nonclustered,
    ParentCateogoryID int null constraint fkCateogory references dbo.Cateogory(CateogoryID)
    )

要件に応じて、本番環境にインデックスオプション(fillfactorなど)を追加することもできます。

7
Andy Jones