1

列のあるテーブルがある場合:

  • アーティスト
  • アルバム
  • NumberOfListens

...クラスター化された主キーをArtist、Album、およびSongに配置するか、自動インクリメントID列を設定して、Artist、Album、およびSongに一意の制約を設定する方が適切です。

データベースの一貫性はどのくらい重要ですか?テーブルの半分にクラスター化された主キーがあり、残りの半分に一意の制約があるid列がある場合、それは悪いですか、それとも問題ではありませんか?どちらの方法も私には同じように見えますが、業界標準が何であるか、どちらが優れているのか、そしてその理由はわかりません。

4

5 に答える 5

5

アーティスト、アルバム、曲などの長いテキストの列に主キーを配置することはありません。クラスター化された PK である自動インクリメント ID を使用します。アーティスト、アルバム、曲をユニークなものにしたい場合は、3 つにユニーク インデックスを追加します。独立したアーティストに関係なく、アルバムまたは曲で検索する場合は、PK を取得するそれぞれのインデックスが必要になるため、小さい PK を使用すると、互いのインデックスを節約できます。節約できるのは、ディスク領域だけでなく、メモリ キャッシュと、ページ上のより多くのキーです。

于 2010-03-02T19:04:37.987 に答える
1

2 つの問題を区別する必要があります。

1)主キーは論理構造であり、テーブル内のすべての行を一意かつ確実に識別する候補キーの 1 つです。これは、INT、GUID、文字列など、実際には何でもかまいません。シナリオに最も適したものを選択してください。外部キー制約で主キーを参照するため、これらはデータベースの整合性にとって重要です。それらを使用してください - 常に - 期間。

2)クラスタリング キー(テーブルの「クラスター化インデックス」を定義する列) - これは物理ストレージに関連するものであり、ここでは、小さく、一意で、安定しており、増加し続けるデータ型が最適です。 - デフォルトのオプションとして INT または BIGINT。

デフォルトでは、SQL Server テーブルの主キーはクラスタリング キーとしても使用されますが、そうである必要はありません。主キーではない列をクラスタリング キーとして簡単に選択できます。

次に、考慮すべき別の問題があります。テーブルのクラスター化キーは、テーブルのすべての非クラスター化インデックスのすべてのエントリにも追加されるため、できるだけ小さくする必要があります。通常、大部分のテーブルには 20 億行以上の INT で十分なはずです。クラスタリング キーとしての VARCHAR(20) などと比較すると、ディスクとサーバー メモリのストレージを数百メガバイト節約できます。

もう少し考えてみましょう - Kimberly Tripp の優れたもの - 読んで、もう一度読んで、消化してください! これは、まさに SQL Server のインデックス作成の福音です。

マルク

于 2010-03-02T19:18:29.887 に答える
0

まず第一に、データが正規化されていないため、ここですでに問題があります。一連のテキスト列に何らかの種類のインデックスを作成することは、可能な限り避けるべきです。これらの列がテキストではない場合でも (そして私はテキストだと思います)、同じテーブルにアーティスト、アルバム、および曲を含めることは意味がありません。このためのはるかに優れた設計は次のようになります。

Artists (
    ArtistID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    ArtistName varchar(100) NOT NULL)

Albums (
    AlbumID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    ArtistID int NOT NULL,
    AlbumName varchar(100) NOT NULL,
    CONSTRAINT FK_Albums_Artists FOREIGN KEY (ArtistID)
        REFERENCES Artists (ArtistID))

Songs (
    SongID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    AlbumID int NOT NULL,
    SongName varchar(100) NOT NULL,
    NumberOfListens int NOT NULL DEFAULT 0
    CONSTRAINT FK_Songs_Albums FOREIGN KEY (AlbumID)
        REFERENCES Albums (AlbumID))

このデザインを作成すると、個々のアルバムやアーティスト、曲を検索できるようになります。また、カバリング インデックスを追加してクエリを高速化することもできます。インデックスははるかに小さいため、元の設計よりも高速になります。

範囲クエリを実行する必要がない場合 (おそらく必要ないでしょう)、IDENTITYキーをROWGUIDif に置き換えることができます。この場合、それはあまり重要ではありません。単純なものに固執しIDENTITYます。

クラスタリング キーには注意が必要です。少しでもシーケンシャルではないキー (アーティスト、アルバム、曲名がシーケンシャルでないことは間違いありません) でクラスター化すると、ページが分割されたり、その他の問題が発生したりします。あなたはこれを望んでいません。Marc が言うように、このキーのコピーはすべてのインデックスに追加されます。キーの長さが 300 または 600 バイトの場合、これは絶対に必要ありません。

特定の曲の再生回数をアーティスト、アルバム、曲名ですばやくクエリできるようにしたい場合、上記の設計では実際には非常に簡単です。適切にインデックスを作成するだけで済みます。

CREATE UNIQUE INDEX IX_Artists_Name ON Artists (ArtistName)
CREATE UNIQUE INDEX IX_Albums_Artist_Name ON Albums (ArtistID, AlbumName)
CREATE UNIQUE INDEX IX_Songs_Album_Name ON Songs (AlbumID, SongName)
    INCLUDE (NumberOfListens)

これで、このクエリは高速になります。

SELECT ArtistName, AlbumName, SongName, NumberOfListens
FROM Artists ar
INNER JOIN Albums al
    ON al.ArtistID = ar.ArtistID
INNER JOIN Songs s
    ON s.AlbumID = al.AlbumID
WHERE ar.ArtistName = @ArtistName
AND al.AlbumName = @AlbumName
AND s.SongName = @SongName

実行計画をチェックアウトすると、3 つのインデックス シークが表示されます。取得できる限り高速です。元の設計とまったく同じ独自性を保証し、速度を最適化しました。さらに重要なことは、正規化されているため、アーティストとアルバムの両方が独自のアイデンティティを持っているため、長期的に管理するのが非常に簡単になります. 「アーティスト X のすべてのアルバム」を検索する方がはるかに簡単です。「アルバム Y のすべての曲」を検索する方がはるかに簡単で高速です

データベースを設計するときは、正規化が最初の関心事であり、インデックス作成は 2 番目の関心事です。そして、正規化された設計が得られると、最適なインデックス作成戦略が明らかになることに気付くでしょう。

于 2010-03-02T19:42:56.660 に答える
0

クラスター化インデックスは、範囲ベースのクエリに最適です。たとえば、記録日や注文日などです。Artist、Album、および Song に 1 つ配置すると、[おそらく] 新しい行を挿入するときに断片化が発生します。

DB がサポートしている場合は、Artist、Album、および Song にクラスター化されていない主キーを追加し、それを良いと呼びます。または、アーティスト、アルバム、曲に一意のキーを追加するだけです。

自動インクリメント主キーを持つことが本当に役立つのは、別のテーブルへの参照整合性が必要な場合だけです。

于 2010-03-02T19:06:20.410 に答える
0

正確な要件を知らなくても、通常はアーティスト テーブルと、アルバム テーブルもあるでしょう。曲テーブルは、アーティスト ID、アルバム ID、曲の一意の組み合わせになります。アプリケーションに応じてインデックスまたは制約によって一意性を強制し、主キーに ID を使用します。

于 2010-03-02T19:06:24.673 に答える