web-dev-qa-db-ja.com

パーティション列の照合順序を変更する(SQL Server 2017)

列の照合順序を変更しようとしています:

ALTER TABLE [dbo].[yourdad] ALTER COLUMN [yourmam] varchar(36) COLLATE SQL_Latin1_General_CP1_CI_AI NOT NULL; 

そしてそれはこのようなメッセージを与えます:

メッセージ5074、レベル16、状態1、行1オブジェクト 'yourdad'は列 'yourmam'に依存しています。メッセージ4922、レベル16、状態9、行1のALTER TABLE ALTER COLUMN yourmamは、1つ以上のオブジェクトがこの列にアクセスするために失敗しました。

この列に依存するパーティションスキーマと関数があります。

現在、照合を変更する必要のある列がある40k以上のテーブルが好きです。

テーブルを再作成せずに照合順序を変更することはできますか?

  1. パーティションインデックスを削除-削除。

  2. しかし、私がスキーマを削除しようとしているとき:

    DROP PARTITION SCHEME yourdad

メッセージ7717、レベル16、状態1、行1現在、パーティション構成「yourdad」は1つ以上のテーブルをパーティション分割するために使用されています。

これは、インストールしたくないデータベースでの大文字と小文字を区別しない新しいデータベース照合であり、古いものは大文字と小文字を区別しました。

6
Mikhail Aksenov

テーブルを削除する必要はありません。

1つのオプション(私がテストしたもの)は次のとおりです。

  1. パーティション化された非クラスター化インデックスを削除します。パーティション化されたクラスター化インデックス、主キー、一意制約をパーティション化されていないファイルグループに移動します。パーティション化されていないファイルグループに(一時的な)クラスター化インデックスを作成して、ヒープのパーティション化を解除します。影響を受けるインデックスと、各インデックスに対して実行する必要があるアクションを特定する方法については、「インスタンス、データベースの照合順序の変更」の "無視されたオブジェクトの検索と修正"セクションに投稿したクエリを参照してください。 、およびすべてのユーザーデータベースのすべての列:何が問題になるのでしょうか? " (これには、クラスター化インデックス、制約、ヒープの処理例も含まれています)。
  2. パーティション構成を削除します
  3. パーティション関数を削除します
  4. 新しい照合で列定義を変更する
  5. パーティション関数を削除して再作成し、入力パラメーターの新しい照合でCOLLATE句を指定します(ここでは、データベースのデフォルトの照合をnot変更していると想定しています。入力パラメータは、COLLATE句を使用して指定されていない限り、文字列型に対してデータベースのデフォルトの照合を使用します。このスキームと関数を使用する_CREATE INDEX_ステートメントは、このパラメータの照合がパーティション列の照合と一致しない場合は失敗します) 。つまり、列の照合順序を_SQL_Latin1_General_CP1_CI_AI_に変更しても、データベースが_SQL_Latin1_General_CP1_CI_AS_を使用している場合は、次のことを行う必要があります。

    _CREATE PARTITION FUNCTION PartitionFunc
    (
      VARCHAR(36) COLLATE SQL_Latin1_General_CP1_CI_AI
    )
    ...
    _

現在、40k以上のテーブルはおそらく数個以上ですが、それらすべてが同じパーティションスキームと関数を使用している場合、これは、すでに必要なものと比較して、4つの追加ステートメント(パーティションスキーマとパーティション関数のドロップと作成)にすぎません。パーティショニングが使用されていなかった場合でも実行します(つまり、インデックスを削除して再作成する必要があります)。そのため、インデックスが削除されて再作成されるため、大量のI/Oが必要になりますが、列の照合順序を変更する場合は、それを回避する方法がありません。

私はこれらの列がnotであると仮定しています(指が交差しています)。

  • クラスタ化インデックスの一部
  • 主キーのキーフィールド、または外部キーを持つ一意のインデックス/制約

これらのケースのいずれかに当てはまる場合は、さらに多くの作業を行う必要がありますが、それはパーティション分割とは関係ありません。


別のオプション(notすべてを再作成したい)might文書化されていないsqlservr.exe -qオプションを使用して、照合順序を変更します[〜#〜] all [〜 #〜]インスタンス上のユーザー列とデータベース。このアプローチでは、データベース、列、パラメーターなどのメタデータを変更してからインデックスを再構築します(これも、照合順序を変更するときに回避策がないため、40k以上のテーブルでは数分(またはそれ以上)かかります)。データベース、または照合をグローバルに更新する場合はインスタンス全体が、その間オフラインになります)。

SQL Server 2019 RC1でこのシナリオをテストしたところ、パーティション関数でnot動作しますが、このアプローチが全体の一部ではないという意味ではありません解決。これは、上記のセクションで説明したプロセスを実行する以外に選択肢がないことを意味します。 sqlservr.exe -qアプローチは、他のすべてを処理します(ユーザー定義のテーブルタイプを除く)。列の照合順序を変更できることには多くの制限があり、データベースのデフォルトの照合順序(両方のケースで多くの依存関係)を変更することにはさらに多くの制限があるため、大文字と小文字を区別するデータベースを今すぐ使用したい場合は、おそらくパーティション化された列だけでなく、他の障害があります。

パーティション関数で機能しないのは、入力パラメーターの照合順序が_sys.partition_parameters_に格納されていることです。この特定のメタデータは、otherwise-awesome-even-if-undocumented-qオプションを使用しても変更されません。これによる影響は次のとおりです。

  1. データがVARCHARでコードページが変更されていない、またはNVARCHARであると仮定すると、データは以前と同じようにパーティション化されます。たとえば、FOR VALUES ( 'D', 'H', 'O', 'V' )を使用する_RANGE LEFT_パーティション関数があるとします。この場合、パーティション#2には値_> D_および_<= H_が含まれています。

    • _SQL_Latin1_General_CP1_CI_AI_の大文字と小文字を区別しない照合を使用する場合、パーティション#2にはEeFfGgHhが含まれます。簡単ですよね?
    • ただし、_SQL_Latin1_General_CP1_CS_AI_の大文字と小文字を区別する照合を使用する場合、パーティション#2にはdEeFfGgHが含まれます。このパーティションには、小文字のdが含まれ、小文字のhは含まれなくなりました。これは、ほとんどのSQL Server照合順序が小文字の前に大文字をソートするためです(Windows照合順序は小文字を最初にソートします)。
  2. データがVARCHARで、コードページが異なる場合の場合、might興味深いものになります。 128から255までの値を持つ文字は、異なる値またはソート位置、あるいはその両方を持つ可能性があります。パーティション関数の照合に使用される照合のコードページ(つまり、「ベストフィット」マッピング)で使用できないため、同様の文字にマップされます。 )、または古いコードページで欠落している可能性があるため、「」となり、そのようにソートされます。使用されている文字、他のコードページへのマッピング(マッピングされている場合でも)、およびパーティション範囲の設定方法に応じて、「まったく効果がない」から「非常に奇妙で難しい」まで、さまざまな体験ができます。トレース/デバッグ動作」。

この特定のメタデータをsqlservr.exe -q操作に追加するようにリクエストを送信しましたが、Microsoftはそれを修正する本当の動機がありません文書化されていない機能であること。ですので、サポートしてください(つまり、投票してください)ので、人々は少なくともそれを望んでいることがわかります(ありがとう!): SQLSERVRを介したパーティション関数とユーザー定義テーブルタイプの照合順序の更新-Q

そうは言っても、2つの主な質問は次のとおりです。

  1. そもそも照合順序を変更するとどのような影響がありますか?現在の照合順序と新しい照合順序は何ですか?

    コードページが変更されている場合、データが失われますか(質問のサンプルコードはVARCHAR列を示しているため、これを可能にします。NVARCHARではそうではありません)?このアプローチはnotコードページ変換を行うため、128〜255の値を持つ文字mightは他の文字になります文字であり、これが発生しても警告/エラーはありません(ただし、そのようなデータがない場合は問題ありません)。

    感度が変化している(つまり、アクセントを区別するからアクセントを区別しない)場合、既存の一意のインデックス/制約の一意性に違反しますか?

  2. すべてに使用される新しい照合順序が必要ですか?もしそうなら、これはうまくいくかもしれません。そうでない場合、このアプローチはすべてを変更するため、実行できません。

このアプローチの詳細については、私の投稿を参照してください:

インスタンス、データベース、およびすべてのユーザーデータベースのすべての列の照合順序の変更:何が問題になるのでしょうか? (役立つクエリを含む「無視されたオブジェクトの検索と修正」セクションを必ず確認してくださいパーティション機能の修正あり)

複数のデータベースがあり、これだけを変更したい場合(ここでも、データベースのデフォルトの照合を含め、このデータベース内のすべてのもの)、次のことができます。

  1. このデータベースをデタッチ(またはバックアップ)します。
  2. この変更を行うためだけに、このデータベースが現在属しているインスタンスに使用されているのと同じインスタンスレベルの照合を使用して、新しい一時的なインスタンスを作成します。
  3. データベースを新しい一時インスタンスに接続(または復元)します。
  4. _sqlservr.exe -q_メソッドを使用して一時インスタンスの照合を更新します。
  5. 一時インスタンスからデータベースをデタッチ(またはバックアップ)します。
  6. 元のインスタンスにデータベースを再接続(または復元)します。
7
Solomon Rutzky

Microsoftのドキュメントによると:

ALTER TABLE ... ALTER COLUMN...

変更する列に関していくつかの制限があります

変更された列は、次のようにすることはできません。

  • タイムスタンプデータ型の列。
  • テーブルのROWGUIDCOL。
  • 計算列、または計算列で使用されます。
  • CREATE STATISTICSステートメントによって生成される統計で使用されます。列がvarchar、nvarchar、またはvarbinaryデータ型でない限り、データ型は変更されません。また、新しいサイズは古いサイズと同じかそれ以上です。または、列が非ヌルからヌルに変更された場合。まず、DROP STATISTICS文を使用して統計を削除します。
  • クエリオプティマイザーによって自動的に生成された統計は、ALTER COLUMNによって自動的に削除されます。
  • PRIMARY KEYまたは[FOREIGN KEY] REFERENCES制約で使用されます。
  • CHECKまたはUNIQUE制約で使用されます。ただし、CHECKまたはUNIQUE制約で使用される可変長列の長さを変更することはできます。
  • デフォルトの定義に関連付けられています。ただし、データ型が変更されない場合は、列の長さ、精度、またはスケールを変更できます。

まったくの量のテーブルで実行可能な場合-データベースをTSQLスクリプトにエクスポートし、照合に関して必要な変更を行います-テーブル内の文字列データ(varchar/nvarchar/textなど)に影響を与えない場合タイプ)、その後、上記のTSQLスクリプトを使用してサーバーを再構築します。

1
eagle275