Database
 sql >> Base de données >  >> RDS >> Database

Plus d'opérations en ligne disponibles maintenant - ou bientôt

J'exécutais des tests dans SQL Database et j'ai découvert au moins une nouvelle opération qui prend en charge ONLINE = ON . C'est sur une version très récente, soit dit en passant - SELECT @@VERSION; continue à donner un ancien numéro de build, mais la preuve est dans la date de build :

Microsoft SQL Azure (RTM) – 12.0.2000.8
12 février 2015 00:53:13
Copyright (c) Microsoft Corporation

Cette version d'Azure SQL Database prend en charge le ONLINE = ON option pour ALTER TABLE ... ALTER COLUMN .

Supposons que vous ayez une table avec une colonne nullable :

CREATE TABLE dbo.a(id INT PRIMARY KEY, x VARCHAR(255));
 
INSERT dbo.a(id, x) SELECT TOP (1) [object_id], name FROM sys.all_objects;

Et maintenant, vous décidez de rendre cette colonne non nullable, vous pouvez le faire (en supposant qu'il n'y a pas de NULL s):

ALTER TABLE dbo.a
  ALTER COLUMN x VARCHAR(255) NOT NULL
  WITH (ONLINE = ON);

Vous pouvez également modifier le classement, le type de données ou la taille de la colonne :

ALTER TABLE dbo.a 
ALTER COLUMN x NVARCHAR(510)    -- changed data type and length
  COLLATE Albanian_BIN NOT NULL -- changed collation and nullability
  WITH (ONLINE = ON);

Dans les versions actuelles de SQL Server (et les versions précédentes d'Azure SQL Database), le ONLINE = ON l'indice n'était pas pris en charge pour ALTER TABLE , et sans l'option, il s'agissait d'une opération de blocage et de taille des données. Pour être juste, la première fois que j'ai exécuté le code, je n'ai pu prouver que la version avec ONLINE = ON a fonctionné avec succès, non pas qu'il a fonctionné comme annoncé.

J'ai exécuté ce code avec ONLINE = ON et sans :

CREATE TABLE dbo.a(id INT PRIMARY KEY, x VARCHAR(255));
 
INSERT dbo.a(id, x) SELECT TOP (1) [object_id], name FROM sys.all_objects;
 
-- placeholder;
 
ALTER TABLE dbo.a 
  ALTER COLUMN x NVARCHAR(510)
  COLLATE Albanian_BIN NOT NULL 
  -- WITH (ONLINE = ON);
 
-- placeholder;
 
DROP TABLE dbo.a;

Dans le --placeholder place, j'ai essayé quelques choses pour déterminer toute différence de comportement (c'était notre base de données SQL de production, donc je ne voulais pas utiliser suffisamment de données ou créer suffisamment d'activité pour que la différence soit évidente). Je voulais vérifier dans les deux scénarios si la page avait changé (indiquant une véritable opération en ligne) ou si les valeurs avaient été mises à jour en place sur les pages existantes (une opération pas si en ligne). J'aurais également pu étendre le test pour voir combien de nouvelles pages ont été créées si les pages étaient pleines et/ou si les 255 caractères étaient utilisés, mais je pensais qu'il suffirait de voir si les pages avaient changé.

J'ai essayé DBCC IND() :

DBCC IND(N'dbname', N'dbo.a', 1, 1);

Les résultats ici n'étaient pas surprenants :

Msg 40518, Niveau 16, État 1
La commande DBCC 'IND' n'est pas prise en charge dans cette version de SQL Server.

Et sys.dm_db_database_page_allocations (le remplacement de DBCC IND ):

SELECT allocated_page_page_id
  FROM sys.dm_db_database_page_allocations(DB_ID(),OBJECT_ID(N'dbo.a'),1,1,N'LIMITED')
  WHERE is_iam_page = 0;

Cela a donné un ensemble de résultats vide - je pense que c'est par conception que cette fonction de gestion dynamique n'expose aucune information physique dans Azure SQL Database.

Ensuite, j'ai essayé une astuce avec fn_PhysLocCracker , dont des gens comme Michelle Ufford (@sqlfool) ont déjà parlé sur leur blog :

SELECT l.page_id FROM dbo.a
  OUTER APPLY sys.fn_PhysLocCracker(%%PhysLoc%%) AS l;

Succès! Cela a renvoyé des valeurs pour les pages utilisées dans l'analyse par rapport à dbo.a , et il est clair que dans le ONLINE = ON version, les données sont déplacées vers de nouvelles pages (laissant vraisemblablement les anciennes disponibles tout au long de l'opération), et sans l'indice, les données et les métadonnées sont mises à jour sur place :

Comparaison de pages sous le comportement ALTER COLUMN standard (à gauche) avec ONLINE =ON (à droite)

Une autre chose que je voulais comparer était les plans d'exécution. Je ne vois peut-être pas grand-chose dans Management Studio, mais dans SQL Sentry Plan Explorer Pro, je peux voir la pile d'appels complète, y compris ce qui se passe dans les coulisses de certaines commandes DDL. Notre outil n'a pas déçu - bien qu'il ne présente pas de plan réel pour la variation de mise à jour sur place, il démontre également qu'il existe une différence de comportement significative lors de l'utilisation de ONLINE = ON :

Comparaison des plans sous le comportement ALTER COLUMN standard (à gauche) avec ONLINE =ON (à droite)

Bien sûr, vous ne verrez cette différence que si vous remplissez toutes les autres conditions requises pour les opérations en ligne (beaucoup sont similaires aux exigences pour la reconstruction d'index en ligne) dans la documentation récemment mise à jour.

Maintenant, si vous n'utilisez pas SQL Database, comment cela vous aide-t-il ? Après tout, cette syntaxe n'est pas analysée correctement même dans la mise à jour cumulative #6 de SQL Server 2014 (12.0.2480). Eh bien, Microsoft n'a pas exactement gardé le fait que le modèle de développement est devenu "le cloud d'abord, puis la boîte" - comme Mark Souza l'a récemment laissé entendre lorsqu'il a tweeté à propos de la nouvelle fonctionnalité de sécurité au niveau des lignes introduite en premier dans Azure SQL Database :

Cela signifie que ces opérations en ligne arriveront probablement bientôt sur votre copie locale de SQL Server. Comme beaucoup d'autres opérations en ligne, gardez à l'esprit que ces choses ont tendance à être réservées à Enterprise Edition.