{"id":402,"date":"2012-08-10T00:26:08","date_gmt":"2012-08-09T22:26:08","guid":{"rendered":"http:\/\/www.sqlserver.fr\/blog\/?p=402"},"modified":"2026-05-02T14:31:03","modified_gmt":"2026-05-02T12:31:03","slug":"difference-entre-top-tablesample","status":"publish","type":"post","link":"https:\/\/www.sqlserver.fr\/blog\/difference-entre-top-tablesample\/","title":{"rendered":"Diff\u00e9rence entre TOP et TABLESAMPLE"},"content":{"rendered":"<p>Voici un petit papier pour comparer les mots-cl\u00e9s TOP et TABLESAMPLE, le TOP \u00e9tant dans les faits trop souvent utilis\u00e9 l\u00e0 o\u00f9 l&rsquo;on devrait utiliser TABLESAMPLE&#8230;<\/p>\n<p>Il s&rsquo;agira ici de comparer \u00e0 la fois la syntaxe d&rsquo;utilisation, les effets et aussi les performances.<!--more--><\/p>\n<p>Les exemples pr\u00e9sent\u00e9s ici s&rsquo;appuieront sur la base\u00a0AdventureWorksDW2012, disponible sur le site <a title=\"SQL Server Product Samples : Database\" href=\"https:\/\/github.com\/Microsoft\/sql-server-samples\/releases\/tag\/adventureworks\" target=\"_blank\" rel=\"noopener noreferrer\">Codeplex<\/a>.<\/p>\n<p>Du point de vue de la syntaxe, la clause TOP se positionne entre le SELECT et le FROM.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">select top 10 PERCENT * from dbo.FactProductInventory<\/pre>\n<p>Au niveau du plan d&rsquo;ex\u00e9cution, on \u00ab\u00a0subit\u00a0\u00bb l&rsquo;index choisi par le moteur (ici l&rsquo;index clustered car on a un SELECT * qui r\u00e9cup\u00e8re donc toutes les colonnes), et on r\u00e9cup\u00e8re les dix premiers pourcents. Cela donne le plan suivant :<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTop.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-672\" title=\"PlanTop\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTop-620x122.png\" alt=\"\" width=\"620\" height=\"122\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTop-620x122.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTop-300x59.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTop.png 648w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>A noter que, comme l&rsquo;index clustered est pris dans l&rsquo;ordre, on r\u00e9cup\u00e8re les premiers enregistrements, ce qui n&rsquo;est pas n\u00e9cessairement id\u00e9al si le besoin est d&rsquo;avoir un aper\u00e7u g\u00e9n\u00e9ral du contenu de la table.<\/p>\n<p>A l&rsquo;inverse, la clause TABLESAMPLE se positionne apr\u00e8s la table, telle une option de for\u00e7age d&rsquo;index ou de type d&rsquo;isolation de verrous.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"sql\">select  * from dbo.FactProductInventory tablesample (10 PERCENT)<\/pre>\n<p>Son fonctionnement est totalement diff\u00e9rent. Il s&rsquo;agit ici de regarder, sur l&rsquo;index choisi (ici encore il s&rsquo;agira de l&rsquo;index clustered), combien de pages de 8Ko sont occup\u00e9es, et d&rsquo;en piocher 10%, au hasard (pas forc\u00e9ment cons\u00e9cutives). A noter aussi qu&rsquo;il ne peut \u00eatre question pour TableSample que de pourcentage, contrairement \u00e0 Top qui peut permettre de r\u00e9cup\u00e9rer un nombre exact de lignes.<\/p>\n<p>Du point de vue de la validit\u00e9 de l&rsquo;\u00e9chantillonage, on est n\u00e9cessairement bien meilleur, car m\u00eame si l&rsquo;on a des blocs de donn\u00e9es adjacentes, ces blocs sont pris au hasard dans le lot et qui plus est arrivent en ordre dispers\u00e9.<\/p>\n<p>Au niveau du plan d&rsquo;ex\u00e9cution, m\u00eame si l&rsquo;on a l\u00e0 encore ce qui appara\u00eet comme un parcours complet d&rsquo;index (index scan), il n&rsquo;en est en fait rien. M\u00eame si c&rsquo;est bien cet index qui est consomm\u00e9, il ne l&rsquo;est que de mani\u00e8re tr\u00e8s parcellaire, seulement quelques pages sont r\u00e9cup\u00e9r\u00e9es deci-del\u00e0.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTableSample.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" title=\"PlanTableSample\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/PlanTableSample.png\" alt=\"\" width=\"538\" height=\"125\" \/><\/a><\/p>\n<p>Point tr\u00e8s important pour le TableSample : le nombre de lignes retourn\u00e9es n&rsquo;est pas, contrairement\u00a0\u00e0 ce qui est le cas pour le TOP, exactement \u00e9gal au pourcentage demand\u00e9 par rapport au nombre total de lignes de la table. Le nombre de pages est bien le dixi\u00e8me du nombre total, mais suivant le remplissage de chaque page (taille des enregistrements, fragmentation, &#8230;), on ne peut pas garantir que l&rsquo;on aura toujours le m\u00eame nombre d&rsquo;\u00e9l\u00e9ments retourn\u00e9s.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Comptage.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-674\" title=\"Comptage\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Comptage.png\" alt=\"\" width=\"458\" height=\"229\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Comptage.png 458w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Comptage-300x150.png 300w\" sizes=\"auto, (max-width: 458px) 100vw, 458px\" \/><\/a>Par contre, en termes de performances, le\u00a0TableSample surclasse tr\u00e8s nettement le Top, qui est lui oblig\u00e9 de mettre en place tout un processus lourd de comptage des enregistrements, l\u00e0 o\u00f9 le TableSample se contentera de renvoyer sans autre forme de proc\u00e8s les donn\u00e9es des pages s\u00e9lectionn\u00e9es.<\/p>\n<p><a href=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Plans.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-675\" title=\"Plans\" src=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Plans-620x247.png\" alt=\"\" width=\"620\" height=\"247\" srcset=\"https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Plans-620x247.png 620w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Plans-300x119.png 300w, https:\/\/www.sqlserver.fr\/blog\/wp-content\/uploads\/2012\/08\/Plans.png 646w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<p>A noter au passage que ces deux mots cl\u00e9s peuvent \u00eatre combin\u00e9s, pour essayer de gommer quelques d\u00e9fauts de l&rsquo;un ou de l&rsquo;autre. Mais en fait, chacun correspond \u00e0 un besoin bien pr\u00e9cis, et il suffira donc de savoir quel est\u00a0notre besoin propre pour choisir la syntaxe ad\u00e9quate.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Voici un petit papier pour comparer les mots-cl\u00e9s TOP et TABLESAMPLE, le TOP \u00e9tant dans les faits trop souvent utilis\u00e9 l\u00e0 o\u00f9 l&rsquo;on devrait utiliser TABLESAMPLE&#8230; Il s&rsquo;agira ici de comparer \u00e0 la fois la syntaxe d&rsquo;utilisation, les effets et &hellip; <a href=\"https:\/\/www.sqlserver.fr\/blog\/difference-entre-top-tablesample\/\">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-402","post","type-post","status-publish","format-standard","hentry","category-article_sql"],"_links":{"self":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/402","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=402"}],"version-history":[{"count":23,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/402\/revisions"}],"predecessor-version":[{"id":1941,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/posts\/402\/revisions\/1941"}],"wp:attachment":[{"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/media?parent=402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/categories?post=402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlserver.fr\/blog\/wp-json\/wp\/v2\/tags?post=402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}