web-dev-qa-db-ja.com

アーカイブテーブルに独自のサロゲートIDキーが必要です

アーカイブテーブルは、独自の代理ID ID /キーを持つ必要がありますか?顧客売上表の例の場合:

  • 元のテーブルと、サロゲートアーカイブIDを持つ追加のアーカイブテーブルがあります。
  • プライマリクラスタインデックスのルールは次のとおりです。
    • 増え続ける
    • 狭い
    • ユニークな
    • 静的

参照:Effective Clustered Indexes (レッドゲートハブ)

私が働いていた最後の会社で、誤って輸入の日や期間を逃した場合、たとえば5月3日のインポートデータが誤って5月4日をスキップし(システムの問題)、5月5日をインポートしたため、新しいアーカイブIDがないと、ページ間にデータを再挿入する必要があり、断片化が発生し、挿入が遅くなります。

アーカイブIDを使用すると、増加し続ける方法で追加することができます。

Archiveidカラムの追加が標準的な業界慣行であるかどうかを問い合わせるだけです。

元のテーブル:

create table dbo.CustomerSalesId
(
    CustomerSalesId bigint primary key identity(1,1),
    CustomerId bigint not null,
    PurchaseDate datetime not null,
    Amount decimal (10,2) not null,
    .........
}

アーカイブテーブル:

create table dbo.ArchiveCustomerSalesId
(
    ArchiveCustomerSalesId bigint primary key identity(1,1),
    CustomerSalesId bigint,
    CustomerId bigint not null,
    PurchaseDate datetime not null,
    Amount decimal (10,2) not null,
    .........
}
create unique index ux_CustomerSalesId on ArchiveCustomerSalesId(CustomerSalesId)
4
user155025

断片化は、あなたが思っているほど悪くはありません。ページの満杯(内部の断片化)は、ページの物理的な順序(外部の断片化)よりもはるかに重要です。

順序どおりに挿入されていない行mightがあると、ページがディスクから読み取られるときのスキャンのパフォーマンスに影響します。メモリからページを読み取るとき、ページが正しい順序であるかどうかは重要ではありません。また、物理サーバーで作業しておらず、ディスクがSAN上にあるLUNである可能性が高いため、ページの連続性の利点はごくわずかです。

内部と外部の断片化の良い視覚的な説明はここにあります: http://www.sqlservercentral.com/blogs/practicalsqldba/2012/04/05/sql-server-index-fragmentation-understanding-fragmentation /

なぜ断片化があなたが思うものではないのかについての素晴らしい記事は、Brent Ozarのブログにあります: https://www.brentozar.com/archive/2012/08/sql-server-index-fragmentation/

ただし、断片化を回避するためだけに追加の代理キーを使用することはお勧めできません。優れたクラスター化インデックスは、最初に、データの検索に最も使用するキーであるため、追加のルックアップを実行する必要はありません。データをアーカイブするときにクラスター化キーを変更する場合、行を見つけるには、前のクラスター化キーの列で一意の非クラスター化インデックスを使用する必要があります。非クラスター化インデックスは、追加のスペースを必要とし、インデックスの一部ではない列を抽出するためのルックアップも必要とするデータのcopyです。

まとめ:いいえ、「archiveId」代理キーを追加する必要はありません。

4
spaghettidba

最近、私が現在取り組んでいるシステムについてこの演習を行いました。現在の代理IDを保持することにしました。

これは主に、歴史的な参照を保持するためでした。 IDを外部参照として使用するさまざまな2次プロセスがあります。これはベストプラクティスではないかもしれませんが、実際の方法です。内部ログもIDを取得します。これらの理由から、アクティブなテーブルのIDをアーカイブテーブルの値に保持したいと思います。同じ目的を実行する別の列を含めるのは冗長に思えました。

断片化に関しては、これは問題ではありません。これらの行は、ポイントルックアップ(行Xの列Yの値は何でしたか)または広範な集計(1月にZがいくつあったか)の2つの状況で使用されます。いずれにせよ、断片化が少しあったとしても害はありません。

ボリュームが大幅に増加し、分析がさらに複雑になると、これを再検討する必要があるかもしれません。おそらく、パーティションとオンライン再構築を使用します(SQL Server 2014以降)。

0
Michael Green