{"id":839,"date":"2013-04-04T22:29:30","date_gmt":"2013-04-04T20:29:30","guid":{"rendered":"http:\/\/www.sqlserver.fr\/blog\/?p=839"},"modified":"2026-05-02T14:30:59","modified_gmt":"2026-05-02T12:30:59","slug":"nombre-de-lignes-dune-table","status":"publish","type":"post","link":"https:\/\/www.sqlserver.fr\/blog\/nombre-de-lignes-dune-table\/","title":{"rendered":"Nombre de lignes d&rsquo;une table"},"content":{"rendered":"<p>Quelle id\u00e9e d&rsquo;\u00e9crire un article pour expliquer comment compter le nombre d&rsquo;enregistrements dans une table ? Tout le monde sait r\u00e9pondre !<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">SELECT COUNT(*) FROM MaTable<\/pre>\n<p>Et bien non, justement ! Il y a bien plus performant &#8230;<!--more--><\/p>\n<p>En effet, lorsque l&rsquo;on compte simplement les lignes d&rsquo;une table avec la syntaxe SELECT COUNT(*), le moteur choisit le plus petit index non filtr\u00e9 sur cette table, et le parcourt enti\u00e8rement en comptabilisant les lignes rencontr\u00e9es.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_Count.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-844\" alt=\"Plan_Count\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_Count-620x207.png\" width=\"620\" height=\"207\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_Count-620x207.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_Count-300x100.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_Count.png 976w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>On constate donc au final un co\u00fbt qui peut \u00eatre non n\u00e9gligeable. (l&rsquo;exemple ci-dessus s&rsquo;appuie sur une table contenant un million d&rsquo;enregistrements).<\/p>\n<p>Et de plus, si quelqu&rsquo;un a commenc\u00e9 (mais pas termin\u00e9) une transaction qui effectue une modification dans cette table, on peut se retrouver bloqu\u00e9 (voir la notion\u00a0<a title=\"ACID\" href=\"https:\/\/fr.wikipedia.org\/wiki\/Propri%C3%A9t%C3%A9s_ACID\" target=\"_blank\" rel=\"noopener noreferrer\">ACID<\/a> et les <a title=\"BEGIN TRANSACTION\" href=\"https:\/\/docs.microsoft.com\/fr-fr\/sql\/t-sql\/language-elements\/begin-transaction-transact-sql\" target=\"_blank\" rel=\"noopener noreferrer\">transactions<\/a>).<\/p>\n<p>Il faut savoir qu&rsquo;en arri\u00e8re plan, SQL Server met \u00e0 disposition des vues syst\u00e8mes qui permettent de consulter entre autres choses l&rsquo;ensemble de la structure d&rsquo;une base de donn\u00e9es, et notamment le nombre d&rsquo;enregistrements dans chaque index.<\/p>\n<p>Il suffit donc de prendre en compte au choix :<\/p>\n<ol>\n<li>l&rsquo;index ayant pour identifiant 0, c&rsquo;est-\u00e0-dire le segment de donn\u00e9es, pour les cas o\u00f9 la table n&rsquo;a pas d&rsquo;index Clustered<\/li>\n<li>l&rsquo;index ayant pour identifiant 1, c&rsquo;est-\u00e0-dire l&rsquo;index clustered, lorsque celui-ci existe.<\/li>\n<\/ol>\n<p>On obtient la requ\u00eate suivante :<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">select sum(p.rows)\r\nfrom sys.partitions p\r\nwhere p.object_id=object_id('[dbo].[MaTable]') and index_id in (0,1)<\/pre>\n<p>Remarque : on utilise l&rsquo;agr\u00e9gat (SUM) afin de prendre en compte les tables partitionn\u00e9es (dont les donn\u00e9es sont sur plusieurs partitions).<\/p>\n<p>Le plan d&rsquo;ex\u00e9cution de cette requ\u00eate, et surtout son co\u00fbt, n&rsquo;a absolument rien \u00e0 voir !<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_SysViews.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-846\" alt=\"Plan_SysViews\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_SysViews-620x221.png\" width=\"620\" height=\"221\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_SysViews-620x221.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_SysViews-300x107.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2013\/04\/Plan_SysViews.png 967w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>Au final, on constate bien que le fait de compter le nombre de lignes d&rsquo;une table peut para\u00eetre trivial mais que la force brute n&rsquo;est pas toujours la meilleure solution (dans le cas pr\u00e9sent, le co\u00fbt de la requ\u00eate varie dans un ratio sup\u00e9rieur \u00e0 10 000 !).<\/p>\n<p>R\u00e9cemment, j&rsquo;ai eu \u00e0 intervenir sur un serveur sur lequel c&rsquo;\u00e9tait ce type de requ\u00eate qui \u00e9taient les plus co\u00fbteuses. Il convient donc de ne pas oublier ce \u00ab\u00a0petit\u00a0\u00bb raccourci &#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quelle id\u00e9e d&rsquo;\u00e9crire un article pour expliquer comment compter le nombre d&rsquo;enregistrements dans une table ? Tout le monde sait r\u00e9pondre ! SELECT COUNT(*) FROM MaTable Et bien non, justement ! Il y a bien plus performant &#8230;<\/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-839","post","type-post","status-publish","format-standard","hentry","category-article_sql"],"_links":{"self":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/839","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=839"}],"version-history":[{"count":14,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/839\/revisions"}],"predecessor-version":[{"id":1935,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/839\/revisions\/1935"}],"wp:attachment":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/media?parent=839"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/categories?post=839"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/tags?post=839"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}