web-dev-qa-db-ja.com

一意でないクラスター化インデックスの管理

最近、SQL Server 2016でデータベースを管理するように割り当てられましたが、データベース内に非一意のクラスター化インデックスを持つ多くのテーブルがあり、非クラスター化主キーインデックスになることがわかりました。

上記は明らかに許可されていますが、理想的ではないことを知っていますが(特に大きなテーブルの場合)、場合によってはそれが理にかなっている可能性がありますが、そのようなテーブルの数から、これは不注意なテーブル定義の結果に似ていることがわかります。

たとえば、Transactionという名前のテーブルには、次のキーを持つクラスター化インデックスがあります:dateis_deleted。また、テーブルにはidという名前の列に非クラスター化主キーがあります。

現在、これらのテーブルの一部はかなり大きく、多くの外部キー参照が含まれているため、このスレッドでのAaronの回答を利用してこれらのすべてのテーブルを変更する以下の手順を思いつきました 非PKをドロップできません外部キー制約で参照されているため、インデックス

  1. テーブルのクラスター化インデックスを削除する
  2. テーブルを参照するすべての外部キー制約を削除します
  3. テーブルの現在の主キー制約を削除します
  4. id列を使用して主キーのクラスター化制約を作成する
  5. 以前に削除されたすべての外部キー制約を作成します
  6. オプション-以前にクラスター化されたインデックスを非クラスター化インデックスとして作成する

大きなテーブルの場合、変更を実行するためにメンテナンスウィンドウを見つける必要があることはわかっていますが、上記の解決策で考えていなかった問題や問題点を見つけましたか?この方法では、残りの非クラスター化インデックスで断片化が発生しますか?

多くのテーブルが関係しているので、副作用を引き起こさないようにしたいと思います。

3
panikkos

これはクエリパターンを知らずに答えるのは難しいですが、すべてのクラスター化インデックスを削除して別のものに置き換えると、間違いなく副作用が発生します。

また、一意ではないクラスター化インデックスを使用するのがずさんなテーブル設計であるか、定義上、最適とは限らないと想定しても、必ずしも正しいとは思いません。

一意ではないクラスター化インデックスを追加すると、SQL Serverは4バイトのuniqueifierをインデックスに追加して、キーに重複する値がある場合にキーが一意になるようにします。この一意名を計算すると、オーバーヘッドが少し追加されますが、あまり劇的ではありません。インデックスブックマークは単一の行を指す必要があるため、この一意識別子は非クラスタ化インデックスにも含まれている必要があります。

一方、あなたが与える例は状況に応じて良いクラスタ化インデックスになるかもしれません:

たとえば、Transactionという名前のテーブルには、日付、is_deletedというキーを持つクラスター化インデックスがあります。また、テーブルのid列に非クラスター化主キーがあります。

これは、同じ日に多くのトランザクションがあり、ほとんどすべてのクエリがSELECT * FROM transactiontable WHERE date = <somedate> AND is_deleted=0

このようなクエリは、非クラスター化インデックスを使用し、キールックアップに頼らなければならない場合、悪影響を与える可能性があります。

どのような副作用を引き起こすかを言うことは不可能ですが、きっとあなたはいくつかの副作用を引き起こすでしょう、そしてこの努力のあなたの理由は間違ったものかもしれません。

これを行うことを主張する場合は、必ず最初にテスト環境でテストしてください。そうすることで、この方法が機能するかどうか、および断片化が発生するかどうかを確認できるはずです(ただし、これはおそらく最小の問題です)心配)。