{"id":707,"date":"2012-09-19T23:08:30","date_gmt":"2012-09-19T21:08:30","guid":{"rendered":"http:\/\/www.sqlserver.fr\/blog\/?p=707"},"modified":"2026-05-02T14:31:02","modified_gmt":"2026-05-02T12:31:02","slug":"ajout-de-colonne-sur-sql-server-2012","status":"publish","type":"post","link":"https:\/\/www.sqlserver.fr\/blog\/ajout-de-colonne-sur-sql-server-2012\/","title":{"rendered":"Ajout de colonne sur SQL Server 2012"},"content":{"rendered":"<p>SQL Server 2012 pr\u00e9sente de nombreuses nouvelles fonctionnalit\u00e9s. En ce qui concerne les performances et la haute disponibilit\u00e9, voici une am\u00e9lioration assez int\u00e9ressante : l&rsquo;ajout de colonnes NOT NULL en tant qu&rsquo;op\u00e9ration en ligne. Elle peut, dans certains cas, rendre quasiment instantann\u00e9 l&rsquo;ajout de nouvelles colonnes m\u00eame si la table contient un tr\u00e8s grand nombre d&rsquo;enregistrements.<!--more--><\/p>\n<p>Pour rappel, SQL Server stocke les donn\u00e9es des tables sous forme de pages de 8Ko. Chaque page contient des lignes compl\u00e8tes (une ligne n&rsquo;est pas \u00e0 cheval sur deux pages). Le contenu des lignes d\u00e9pendant du type d&rsquo;index : toutes les colonnes de la table pour les index clustered ou les segments, ou bien uniquement un sous-ensemble dans le cas des index non clustered.<\/p>\n<p>Consid\u00e9rons une table avec un index clustered. Les pages de cet index contiennent toutes les colonnes de la table. Mais si l&rsquo;on cherche \u00e0 ajouter une colonne \u00e0 la table, il convient de reprendre toutes les lignes, et donc toutes les pages, pour ajouter cette nouvelle colonne. Lorsque la table contient un grand nombre d&rsquo;enregistrements, l&rsquo;op\u00e9ration peut s&rsquo;av\u00e9rer tr\u00e8s co\u00fbteuse.<\/p>\n<p>Prenons l&rsquo;exemple ci-dessous, sous SQL Server 2008 R2. D&rsquo;abord, la cr\u00e9ation de la table et son remplissage.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TableVolumineuse]') AND type in (N'U'))\r\nBEGIN\r\nCREATE TABLE [dbo].[TableVolumineuse](\r\n\t[Id] [int] IDENTITY(1,1) NOT NULL,\r\n\t[Chaine1] [char](2000) NOT NULL,\r\n CONSTRAINT [PK_TableVolumineuse] PRIMARY KEY CLUSTERED \r\n(\r\n\t[Id] ASC\r\n)) ON [PRIMARY]\r\nEND\r\nGO\r\nset nocount on\r\ngo\r\ninsert into TableVolumineuse(Chaine1) values ('')\r\nGO 1000000<\/pre>\n<p>Cette table contient un volume de donn\u00e9es non n\u00e9gligeable.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Volumetrie.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-711\" title=\"Volumetrie\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Volumetrie.png\" alt=\"\" width=\"472\" height=\"124\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Volumetrie.png 472w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Volumetrie-300x78.png 300w\" sizes=\"auto, (max-width: 472px) 100vw, 472px\" \/><\/a>Si l&rsquo;on doit maintenant ajouter une autre colonne, toutes ces pages devront \u00eatre retouch\u00e9es, et les\u00a0ressources disque consomm\u00e9es par cette op\u00e9ration seront tr\u00e8s\u00a0importantes.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">alter table TableVolumineuse add DateHeure datetime NOT NULL DEFAULT '20121225'<\/pre>\n<p>La trace du profiler donne les valeurs suivantes :<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2008.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-713\" title=\"Trace2008\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2008-620x52.png\" alt=\"\" width=\"620\" height=\"52\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2008-620x52.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2008-300x25.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2008.png 1005w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>Non seulement on voit 250000 lectures de pages et autant d&rsquo;\u00e9critures, mais aussi de nombreuses secondes (de l&rsquo;ordre de 3 minutes sur la machine sur laquelle j&rsquo;ai lanc\u00e9 ce test) d&rsquo;ex\u00e9cution du processus. Et pendant tout ce processus, la structure de la table est verrouill\u00e9e car en cours de modification, ce qui signifie qu&rsquo;aucune requ\u00eate ne peut \u00eatre ex\u00e9cut\u00e9e sur cette table.<\/p>\n<p>Dans un contexte de donn\u00e9es critiques avec de nombreuses connexions et un SLA exigeant, un tel blocage est tr\u00e8s difficile \u00e0 faire passer&#8230;<\/p>\n<p>SQL 2012 pr\u00e9sente donc dans son \u00e9dition Enterprise (\u00e9dition d\u00e9di\u00e9e \u00e0 ce type d&rsquo;environnements exigeants) un comportement beaucoup plus int\u00e9ressant. L&rsquo;ajout d&rsquo;une colonne valu\u00e9e avec une constante d&rsquo;ex\u00e9cution (c&rsquo;est-\u00e0-dire une valeur ne d\u00e9pendant pas de la ligne) s&rsquo;effectue uniquement sous forme de m\u00e9tadata. Plus tard, lorsqu&rsquo;une des pages aura besoin d&rsquo;\u00eatre \u00e9crite (lors de la mise \u00e0 jour d&rsquo;enregistrements, ou lors de la reconstruction d&rsquo;index), le syst\u00e8me en profitera pour int\u00e9grer la nouvelle colonne. Et en attendant, les m\u00e9tadatas suffiront pour que les instructions de type SELECT se comportent comme si la colonne avait effectivement \u00e9t\u00e9 pleinement ins\u00e9r\u00e9e. (plus d&rsquo;informations comme d&rsquo;habitude sur l&rsquo;<a title=\"ALTER TABLE (Transact-SQL)\" href=\"https:\/\/docs.microsoft.com\/fr-fr\/sql\/t-sql\/statements\/alter-table-transact-sql\" target=\"_blank\" rel=\"noopener noreferrer\">aide en ligne<\/a>).<\/p>\n<p>La d\u00e9monstration est tr\u00e8s parlante, en relan\u00e7ant la m\u00eame requ\u00eate d&rsquo;ajout de colonne que ci-dessus, mais cette fois-ci en environnement SQL Server 2012.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">alter table TableVolumineuse add DateHeure datetime NOT NULL DEFAULT '20121225'<\/pre>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2012.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-714\" title=\"Trace2012\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2012-620x52.png\" alt=\"\" width=\"620\" height=\"52\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2012-620x52.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2012-300x25.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/09\/Trace2012.png 952w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>D&rsquo;une dur\u00e9e de 3 minutes, nous sommes pass\u00e9s en dessous du dixi\u00e8me de seconde, ce qui ne manquera pas de satisfaire les clients exigeants&#8230;<\/p>\n<p>Cette fonctionnalit\u00e9 ne n\u00e9cessite pas d&rsquo;action particuli\u00e8re pour \u00eatre activ\u00e9e, elle l&rsquo;est automatiquement dans l&rsquo;\u00e9dition Enterprise de SQL Server 2012. Et tout DBA en conviendra, des modifications de structure si rapides montrent pleinement les efforts qui ont \u00e9t\u00e9 apport\u00e9s sur les performances et la haute disponibilt\u00e9&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>SQL Server 2012 pr\u00e9sente de nombreuses nouvelles fonctionnalit\u00e9s. En ce qui concerne les performances et la haute disponibilit\u00e9, voici une am\u00e9lioration assez int\u00e9ressante : l&rsquo;ajout de colonnes NOT NULL en tant qu&rsquo;op\u00e9ration en ligne. Elle peut, dans certains cas, rendre &hellip; <a href=\"https:\/\/www.sqlserver.fr\/blog\/ajout-de-colonne-sur-sql-server-2012\/\">Continuer la lecture <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-707","post","type-post","status-publish","format-standard","hentry","category-article_sql"],"_links":{"self":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/707","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/comments?post=707"}],"version-history":[{"count":18,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/707\/revisions"}],"predecessor-version":[{"id":1939,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/707\/revisions\/1939"}],"wp:attachment":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/media?parent=707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/categories?post=707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/tags?post=707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}