Nous avons un tableau avec 2,3 milliards de lignes. Nous aimerions changer une colonne de NOT NULL à NULL. La colonne est contenue dans un index (pas l'index cluster ou PK). Le type de données ne change pas (c'est un INT). Juste la nullité. La déclaration est la suivante:
Alter Table dbo.Workflow Alter Column LineId Int NULL
L'opération prend plus de 10 avant de l'arrêter (nous ne l'avons même pas encore laissée se terminer car c'est une opération de blocage et prenait trop de temps). Nous allons probablement copier la table sur un serveur de développement et tester le temps qu'il faut réellement. Mais, je suis curieux de savoir si quelqu'un sait ce que SQL Server fait sous le capot lors de la conversion de NOT NULL en NULL? De plus, les index affectés devront-ils être reconstruits? Le plan de requête généré n'indique pas ce qui se passe.
La table en question est groupée (pas un tas).
la source
Réponses:
Comme mentionné par @Souplex dans les commentaires, une explication possible pourrait être si cette colonne est la première
NULL
colonne de table de l'index non cluster auquel elle participe.Pour la configuration suivante
sys.dm_db_index_physical_stats montre que l'index non clusterisé
ix
a 248 pages feuilles et une seule page racine.Une ligne typique dans une page feuille d'index ressemble à
Et dans la page racine
Puis en cours d'exécution ...
Revenu
En vérifiant à nouveau la feuille d'index, les lignes ressemblent maintenant à
et les lignes dans les pages de niveau supérieur comme ci-dessous.
Chaque ligne a été mise à jour et contient désormais deux octets pour le nombre de colonnes ainsi qu'un autre octet pour NULL_BITMAP.
En raison de la largeur de ligne supplémentaire, l'index non cluster a maintenant 285 pages feuilles et maintenant deux pages de niveau intermédiaire avec la page racine.
Le plan d'exécution du
ressemble à ceci
Cela crée une toute nouvelle copie de l'index plutôt que de mettre à jour l'existant et de devoir fractionner les pages.
la source
Il va certainement recréer l'index non clusterisé et pas seulement mettre à jour les métadonnées. Ceci est testé sur SQL 2014 et ne devrait vraiment pas être testé sur un système de production:
Et maintenant pour la partie amusante:
Cela nous donnera les pages de base de données où la table et l'index non cluster sont stockés.
Recherchez
PagePID
oùIndexID
est 2 etPageType
est 2, puis procédez comme suit:et alors:
Notez qu'il y a un bitmap nul dans l'en-tête:
Faisons maintenant:
Si vous êtes vraiment impatient, vous pouvez réessayer d'exécuter la
dbcc page
commande mais elle échouera, alors vérifions à nouveau l'allocation avecDBCC IND (0, z, -1)
. La page se déplacera comme par magie.Ainsi, la modification de la nullité d'une colonne affectera le stockage des index non cluster qui couvrent cette colonne, car les métadonnées doivent être mises à jour et vous ne devriez pas avoir besoin de reconstruire les index par la suite.
De nombreuses
ALTER TABLE ... ALTER COLUMN ...
opérations peuvent être effectuées àONLINE
partir de SQL Server 2016, mais:la source