web-dev-qa-db-fra.com

Supprimer et recréer des tables SSDT lorsque rien n'a changé

Nous avons un projet de base de données Visual Studio composé d'environ 129 tables. Il s'agit de la base de données principale de notre produit CRM/Call Center interne basé sur le Web, qui est toujours en cours de développement.

Nous utilisons la publication SSDT à partir de VS pour déployer sur des instances au fur et à mesure des modifications. Nous développons localement via SQL Express (2016), avons également un environnement LAB pour les tests de performances et de charge exécutant SQL 2014, un environnement UAT exécutant 2012 et enfin un déploiement en production qui exécute SQL 2016.

Tous les environnements (sauf la production) le script généré lors de la publication est très bon, seulement les changements. Le script de production fait beaucoup plus de travail. Semble supprimer et recréer beaucoup plus de tables, que je sais n'ont pas changé (37 tables déployées en dernier). Certains de ces tableaux ont des lignes dans les millions, et la publication entière prend plus de 25 minutes.

Si je répète la publication en production, elle baisse à nouveau et recrée 37 tableaux. La base de données de production a une réplication que je dois désactiver avant les déploiements (je ne sais pas si c'est un facteur).

Je ne comprends pas ce que la publication Production veut toujours supprimer et recréer des tableaux même si rien n'a changé. J'espère obtenir des conseils sur où chercher pour savoir pourquoi SSDT pense que ceux-ci doivent être recréés.

à l'aide de Visual Studio Professional 2017 V 15.5.5 et SSDT 15.1

6
OJay

Après pas mal de frustration, finalement trouvé la cause, et poster comme réponse car cela peut aider les autres ....

Trouver la raison pour laquelle SSDT pensait que le schéma était différent, je pense que c'est le premier point d'appel. SQL Scheme compare est votre ami ici. (Dans VS sous Tools => SQL => New Scheme Comparison ...)

Tout d'abord grâce à @ jadarnel27, cela a été très utile, alors applaudissez, mais ce n'était pas la réponse, j'ai peur. Les définitions de colonnes calculées et les définitions de contraintes étaient certainement des candidats, tout comme le classement potentiel des colonnes. Ironiquement, j'ai eu un problème avec une colonne calculée, mais ce n'était pas la définition, c'était le fait que je n'ai pas ajouté NOT NULL à la fin de la définition de la colonne (qui est bien sûr la valeur par défaut) mais SSDT a vu cela comme différent à chaque fois.

J'ai donc dû changer une colonne de

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

à

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

puis il a cessé constamment de supprimer et de recréer la colonne. Cela est apparu dans Scheme Compare, pas dans la définition de la colonne calculée.

Deuxièmement, parce que nous utilisions la réplication, SQL ajoutait NOT FOR REPLICATION à la plupart des tables qui étaient utilisées dans la réplication (les raisons en sont liées aux travaux de réplication) mais, en substance, changeait une table DDL de

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
)

encore une fois cela est apparu sur Scheme compare ......

et pour résoudre ce problème, ajoutez NOT FOR REPLICATION dans le code source DDL dans VS pour toutes les tables requises ou sous les paramètres de publication -> Advance -> Ignore tab et faites défiler vers le bas, cochez la case ci-dessous: SSDT Publish Advance Ignore Not For Replication

et puis tout était disco

10
OJay

Plusieurs éléments peuvent entraîner la génération de ce type d'action de "déplacement de table" ou de "reconstruction de table" par le processus de publication SSDT.

Normalisation des expressions

La raison la plus courante que j'ai rencontrée est que vous avez calculé (ou persisté) des colonnes dans ces tables, et que vous utilisez une fonction ou une expression intégrée que SQL Server souhaite changer en une forme plus standard.

J'ai un peu écrit à ce sujet sur mon blog: problèmes SSDT: déployer le même changement encore et encore

Si vous avez des colonnes calculées, examinez votre code source, puis comparez-le à la valeur stockée réelle dans votre base de données de production en exécutant cette requête:

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

Si c'est différent, mettez à jour votre code source pour qu'il corresponde à ce qui est stocké dans sys.computed_columns, et vous devriez être prêt à partir.

Comme je l'ai mentionné dans le blog, une autre cause de la reconstruction pourrait être une situation similaire avec une contrainte CHECK sur l'une des colonnes de cette table.

Une liste non exhaustive des éléments à rechercher dans les définitions de contraintes ou de colonnes calculées:

  • CAST (est changé en CONVERT)
  • IN (obtient changé en une liste de OR instructions)
  • ENTRE (converti en deux déclarations d'inégalité)

Ordinalité de la colonne

Par défaut, si les colonnes telles qu'écrites dans votre code source ne sont pas dans l'ordre par rapport à ce qu'elles sont dans la table de destination, SSDT reconstruira la table pour les récupérer dans le même ordre.

Vous pouvez désactiver ce comportement en définissant la propriété "ignorer l'ordre des colonnes" des options de publication avancées.

screenshot ignore column order option

2
Josh Darnell

J'ai eu un problème similaire avec une table de plusieurs millions de lignes dans une base de données de production en cours de reconstruction à chaque déploiement, seule la table affectée n'avait pas de colonnes, de fonctions, de réplication calculées, etc.

Je pense qu'il y a une cause plus générale à ce problème que mentionné précédemment, et c'est les différences entre la définition de la table telle qu'elle est stockée dans le contrôle de source et le normalisé par le moteur = définition à la cible . Essayez de créer un script pour la table à partir de l'explorateur d'objets SSMS (accédez à la table> cliquez avec le bouton droit sur> Table de script en tant que> CRÉER vers> Nouvelle fenêtre de l'éditeur de requête). Si vous voyez beaucoup de détails supplémentaires dans la définition, par exemple les options d'index, incluent celles du contrôle de code source.

Par exemple, cette instruction CREATE TABLE:

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

écrit comme:

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

Vous pouvez ranger l'horrible formatage, assurez-vous simplement de conserver la définition telle quelle. Vous devrez peut-être modifier les options de script SSMS (Outil> Options> Explorateur d'objets SQL Server> Script) pour révéler la définition complète. Si de nombreuses tables doivent être corrigées, essayez de les créer au niveau de la base de données (accédez à la base de données> cliquez avec le bouton droit> Tâches> Générer des scripts ...) ou générez un script de publication sur une base de données vide.

0
nimbell