最近、SQL Server 2016でデータベースを管理するように割り当てられましたが、データベース内に非一意のクラスター化インデックスを持つ多くのテーブルがあり、非クラスター化主キーインデックスになることがわかりました。
上記は明らかに許可されていますが、理想的ではないことを知っていますが(特に大きなテーブルの場合)、場合によってはそれが理にかなっている可能性がありますが、そのようなテーブルの数から、これは不注意なテーブル定義の結果に似ていることがわかります。
たとえば、Transaction
という名前のテーブルには、次のキーを持つクラスター化インデックスがあります:date
、is_deleted
。また、テーブルにはid
という名前の列に非クラスター化主キーがあります。
現在、これらのテーブルの一部はかなり大きく、多くの外部キー参照が含まれているため、このスレッドでのAaronの回答を利用してこれらのすべてのテーブルを変更する以下の手順を思いつきました 非PKをドロップできません外部キー制約で参照されているため、インデックス :
id
列を使用して主キーのクラスター化制約を作成する大きなテーブルの場合、変更を実行するためにメンテナンスウィンドウを見つける必要があることはわかっていますが、上記の解決策で考えていなかった問題や問題点を見つけましたか?この方法では、残りの非クラスター化インデックスで断片化が発生しますか?
多くのテーブルが関係しているので、副作用を引き起こさないようにしたいと思います。
これはクエリパターンを知らずに答えるのは難しいですが、すべてのクラスター化インデックスを削除して別のものに置き換えると、間違いなく副作用が発生します。
また、一意ではないクラスター化インデックスを使用するのがずさんなテーブル設計であるか、定義上、最適とは限らないと想定しても、必ずしも正しいとは思いません。
一意ではないクラスター化インデックスを追加すると、SQL Serverは4バイトのuniqueifier
をインデックスに追加して、キーに重複する値がある場合にキーが一意になるようにします。この一意名を計算すると、オーバーヘッドが少し追加されますが、あまり劇的ではありません。インデックスブックマークは単一の行を指す必要があるため、この一意識別子は非クラスタ化インデックスにも含まれている必要があります。
一方、あなたが与える例は状況に応じて良いクラスタ化インデックスになるかもしれません:
たとえば、Transactionという名前のテーブルには、日付、is_deletedというキーを持つクラスター化インデックスがあります。また、テーブルのid列に非クラスター化主キーがあります。
これは、同じ日に多くのトランザクションがあり、ほとんどすべてのクエリがSELECT * FROM transactiontable WHERE date = <somedate> AND is_deleted=0
。
このようなクエリは、非クラスター化インデックスを使用し、キールックアップに頼らなければならない場合、悪影響を与える可能性があります。
どのような副作用を引き起こすかを言うことは不可能ですが、きっとあなたはいくつかの副作用を引き起こすでしょう、そしてこの努力のあなたの理由は間違ったものかもしれません。
これを行うことを主張する場合は、必ず最初にテスト環境でテストしてください。そうすることで、この方法が機能するかどうか、および断片化が発生するかどうかを確認できるはずです(ただし、これはおそらく最小の問題です)心配)。