現在、2列のcategories
テーブルがあります-category VARCHAR(50) NOT NULL PRIMARY KEY
とparent VARCHAR(50)
。 parent
列は、category
列への外部キー(FK)です。
これは最も明白なアプローチのようです。ただし、主キーにVARCHAR
列を使用しているため、アラームベルが頭の中で鳴っています。これにより、テーブルを照会するときの操作が遅くなる可能性があります。
cat_id INT AUTO_INCREMENT
という3番目の列を導入してPKに設定することもできますが、意味のない新しい列が導入されます。
どちらが高速になるかとは別に、他にどのような考慮事項を検討する必要がありますか?
最大で1000カテゴリ程度になると予測しているため、行数はそれほど多くありません。ただし、categories
PK列は、他のテーブルの多くの外部キーの参照列になります。
PKとして(一意の)ユーザー名を使用する必要がありますか?
主キーとしてのVARCHAR
列は、通常同じ列にクラスターインデックスを作成するため、適切な選択ではありません。
VARCHAR列のクラスターインデックスは、断片化率が高いことが予想されるため、不適切な選択です。新しく挿入されるすべてのキー値は、既存のキーの間のどこかでその場所を見つけようとし、通常はページ分割と高インデックスの断片化を引き起こします。その結果、パフォーマンスが低下し、追加のインデックスの再構築/再編成コストが発生します。
次に、varchar
キー列を外部キーとして使用すると、疑似キーauto-incremented
列と比較して余分なスペースが必要になります。
だが
自動インクリメントされた列のクラスター化インデックスは、「ホットスポット」を作成する場合があります。これを注意深く読んでください 「インクリメントキーに基づいてクラスタ化インデックスを作成しないでください」というSQL Server 2000日の神話はありますか?
ホットスポットが問題になる可能性がありますが、多くのユーザーが値を挿入しようとしていますが、あなたの場合はvarcharと比較して自動インクリメントされた列に移動したいと思います。
はい、代理の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など)を追加することもできます。