web-dev-qa-db-ja.com

何も変更されていない場合のSSDTドロップおよび再作成テーブル

約129のテーブルで構成されるVisual Studioデータベースプロジェクトがあります。これは、現在開発中の社内WebベースのCRM /コールセンター製品のプライマリデータベースです。

VS内からSSDT Publishを使用して、変更が加えられたときにインスタンスにデプロイします。 SQL Express(2016)を介してローカルで開発し、SQL 2014を実行するパフォーマンスと負荷テストのためのLAB環境、2012を実行するUAT環境、そして最後にSQL 2016を実行する本番環境にデプロイします。

すべての環境(本番環境を除く)で、発行時に生成されるスクリプトは非常に優れており、変更のみを行います。本番スクリプトは、さらに多くの作業を行います。変更していないことがわかっている多くのテーブルを削除して再作成しているようです(37個のテーブルが最後に展開されました)。これらのテーブルの一部には数百万の行があり、パブリッシュ全体で25分以上かかります。

本番へのパブリッシュを繰り返すと、37のテーブルが再び削除されて再作成されます。実動DBには、デプロイメントの前に無効にする必要があるレプリケーションがあります(それが要因であるかどうかは不明です)。

何も変更されていなくても、プロダクションパブリッシュが常にテーブルを削除して再作成したいのかわかりません。 SSDTがこれらを再作成する必要があると考える理由を確立するためにどこを見ればよいかについて、いくつかのアドバイスを期待しています。

visual Studio Professional 2017 V 15.5.5およびSSDT 15.1を使用

6
OJay

かなりの欲求不満の後、最終的に原因を見つけ、それが他の人を助けるかもしれないので、回答として投稿しました...

SSDTがスキームが異なると思った理由を見つけることが、私が最初に電話するポイントだと思います。 SQLスキーマの比較は、ここであなたの友達です。 (VSでは、ツール=> SQL =>新しいスキームの比較...)

まず、@ jadarnel27に感謝します。とても役に立ったので、おめでとうございますが、私が恐れている答えではありませんでした。計算された列の定義と制約の定義は、列の順序付けの可能性があるため、間違いなく候補でした。皮肉なことに、計算列に1つの問題がありましたが、それは定義ではありませんでした。列定義の最後にNOT NULLを追加しなかったためです(もちろん、これはデフォルトです)が、SSDTはそれを別のものと見なしました毎回。

だから私はから列を変更する必要がありました

[ColumnName] AS (CONCAT(Col1,' ',Col2)) PERSISTED

[ColumnName] AS (CONCAT(Col1,' ',Col2)) PERSISTED NOT NULL

その後、列の削除と再作成が常に停止しました。これは、計算された列の定義ではなく、Scheme Compareに表示されました。

次に、レプリケーションを使用していたため、SQLはレプリケーションで使用されていたほとんどのテーブルにNOT FOR REPLICATIONを追加していました(理由はレプリケーションの処理に関係するため)が、本質的にはテーブルDDLを

CREATE TABLE [dbo].[Whatever]
(
    [WhateverId]    INT IDENTITY(1,1) NOT NULL
    ...etc more columns
)

CREATE TABLE [dbo].[Whatever]
(
    [WhateverId]    INT IDENTITY(1,1) NOT FOR REPLICATION NOT NULL
    ...etc more columns
)

再びこれはスキーム比較に現れました......

修正するには、必要なすべてのテーブルのVSのDDLソースコードにNOT FOR REPLICATIONを追加するか、パブリッシュ設定-> Advance-> Ignoreタブで少し下にスクロールして、以下のようにボックスをチェックします: SSDT Publish Advance Ignore Not For Replication

そして、すべてが ディスコ でした

10
OJay

SSDT公開プロセスによって、この種の「テーブル移動」または「テーブル再構築」アクションが生成される原因にはいくつかあります。

式の標準化

私が遭遇した最も一般的な理由は、それらのテーブルに計算された(または永続的な計算された)列があり、SQL Serverがより標準的なフォームに変更したい組み込み関数または式を使用していることです。

私はこれについてブログで少し書きました: SSDTの問題:同じ変更を何度もデプロイする

計算列がある場合は、ソースコードを確認し、次のクエリを実行して、実稼働データベースに実際に格納されている値と比較します。

select [definition] 
from sys.computed_columns 
where [name] = 'YourColumnName';

異なる場合は、sys.computed_columnsに格納されているものと一致するようにソースコードを更新すれば、問題ありません。

ブログで述べたように、再構築の別の原因は、そのテーブルの列の1つにCHECK制約が設定されている同様の状況である可能性があります。

制約または計算された列定義で検索するものの非網羅的なリスト:

  • CAST(CONVERTに変更されます)
  • IN(ORステートメントのリストに変更されます)
  • BETWEEN(2つの不平等ステートメントに変換されます)

列の順序

デフォルトでは、ソースコードで記述された列が宛先テーブルの列と異なる場合、SSDTはテーブルを再構築して同じ順序に戻します。

詳細なパブリッシュオプションの「列の順序を無視する」プロパティを設定することで、この動作を無効にすることができます。

screenshot ignore column order option

2
Josh Darnell

運用データベースの数百万行のテーブルが展開ごとに再構築されるという同様の問題がありました。影響を受けたテーブルだけに、計算された列、関数、レプリケーションなどがありませんでした。

この問題には、前述の問題よりも一般的な原因があると思います。これは、ソース定義に格納されているテーブル定義とengine-normalized違いです=ターゲットでの定義。 SSMSオブジェクトエクスプローラーからテーブルのスクリプトを作成してみてください(テーブルにドリルダウンし、右クリック> [テーブルのスクリプトを作成]> [作成先]> [新しいクエリエディターウィンドウ])。定義に多くの詳細が表示される場合。インデックスオプションには、ソース管理のオプションが含まれます。

たとえば、次のCREATE TABLEステートメントは次のとおりです。

CREATE TABLE dbo.MyTable (
  SomeNumber int NOT NULL
, SomeText varchar(100) NULL
, CONSTRAINT PK_SomeNumber PRIMARY KEY CLUSTERED (SomeNumber)
)

スクリプトとして:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[MyTable](
    [SomeNumber] [int] NOT NULL,
    [SomeText] [varchar](100) NULL,
 CONSTRAINT [PK_SomeNumber] PRIMARY KEY CLUSTERED 
(
    [SomeNumber] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

恐ろしいフォーマットを片付けることができますが、定義はそのままにしてください。完全な定義を表示するには、SSMSスクリプトオプション([ツール]> [オプション]> [SQL Serverオブジェクトエクスプローラー]> [スクリプト])を変更する必要がある場合があります。修正する必要のあるテーブルが多数ある場合は、データベースレベルでスクリプトを実行して(データベースにドリルダウンし、右クリック> [タスク]> [スクリプトの生成...]を実行するか、空のデータベースに対してパブリッシュスクリプトを生成します。

0
nimbell