{"id":930,"date":"2012-04-29T16:31:29","date_gmt":"2012-04-29T20:31:29","guid":{"rendered":"http:\/\/sqlity.net\/en\/?p=930"},"modified":"2014-11-13T13:59:00","modified_gmt":"2014-11-13T18:59:00","slug":"the-unloved-backward-scan","status":"publish","type":"post","link":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/","title":{"rendered":"The Unloved Backward Scan"},"content":{"rendered":"<div>\n<h3>Introduction<\/h3>\n<p>\nWhen a query requires rows to be sorted, either directly requested with an <span class=\"tt\">ORDER BY<\/span> clause or because one of the iterators requires it, SQL Server has two options to guarantee that order. The obvious one is to utilize a sort iterator. If the data comes from an index (clustered or covering), SQL Server can also use an \"Ordered Scan\" of the data. Depending on the requested sort direction, such an ordered scan can be either forward or backward.\n<\/p>\n<p>\nThis would hardly be worth an article, if there wasn't the peculiarity that SQL Server obviously does not like the idea of having to execute an ordered scan that is directed backwards.\n<\/p>\n<h3>Backward Scan Dislike<\/h3>\n<p>\nLet's look at an example. First we need some tables with data:\n<\/p>\n<div>\n[sql]\nIF OBJECT_ID('dbo.T1') IS NOT NULL DROP TABLE dbo.T1;<br \/>\nIF OBJECT_ID('dbo.T2') IS NOT NULL DROP TABLE dbo.T2;<\/p>\n<p>CREATE TABLE dbo.T1(<br \/>\nId INT CONSTRAINT T1_PK PRIMARY KEY CLUSTERED,<br \/>\nv1 INT,<br \/>\nc1 VARCHAR(8000)<br \/>\n);<\/p>\n<p>CREATE TABLE dbo.T2(<br \/>\nId INT CONSTRAINT T2_PK PRIMARY KEY CLUSTERED,<br \/>\nv1 INT,<br \/>\nc1 VARCHAR(8000)<br \/>\n);<\/p>\n<p>INSERT INTO dbo.T1(Id,v1,c1)<br \/>\nSELECT n,CHECKSUM(NEWID()),'*'<br \/>\nFROM dbo.GetNums(1000000);<\/p>\n<p>INSERT INTO dbo.T2(Id,v1,c1)<br \/>\nSELECT n,CHECKSUM(NEWID()),'*'<br \/>\nFROM dbo.GetNums(1000000);<br \/>\n--Get dbo.GetNums here: http:\/\/www.sqlmag.com\/article\/sql-server\/virtual-auxiliary-table-of-numbers<br \/>\n[\/sql]\n<\/p><\/div>\n<p>\nThis script is creating two tables containing one million rows each. The v1 column is filled with random values; the c1 column just contains a single constant character. The Id column is the clustered primary key and it is providing the ordering on disk that we are going to use.\n<\/p>\n<p>\nThe query is a little made up. It joins T2 to itself bringing back only one set of columns. It also restricts the result of this join to the first one million rows, sorted by T2.Id. The one million values in T2.v1 are random from a set of 4 billion making them \"mostly\" unique. That means the self-join is expected to return about one million rows anyway. Those rows are then joined to T1. In the end the <span class=\"tt\">ORDER BY<\/span> requests that all rows be returned sorted by the Id column of the T1 table:\n<\/p>\n<div>\n[sql]\nSELECT  *<br \/>\nFROM    dbo.T1 A<br \/>\n        INNER JOIN ( SELECT TOP ( 1000000 )<br \/>\n                            B.*<br \/>\n                     FROM   dbo.T2 B<br \/>\n                            INNER JOIN dbo.T2 C ON B.v1 = C.v1<br \/>\n                     ORDER BY B.Id<br \/>\n                   ) BC ON A.Id = BC.Id<br \/>\nORDER BY A.Id;<br \/>\n[\/sql]\n<\/div>\n<p>\nThe execution plan of this query looks like this:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png\" alt=\"Plan with Forward Scan\" title=\"Plan with Forward Scan\" width=\"1123\" height=\"248\" class=\"aligncenter size-full wp-image-937\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png 1123w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan-300x66.png 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan-1024x226.png 1024w\" sizes=\"auto, (max-width: 1123px) 100vw, 1123px\" \/><\/a>\n<\/p>\n<p>\nThere is nothing unexpected in this plan. The T2 self-join is done with a hash join operator, as there is no index on the v1 column. The data is then sorted by a sort operator and passed through a serial zone for the top operator. After that there is no additional sort operator for the data to pass through. As the merge join requires both streams to be sorted the same way on the join column, this means that the data must be produced sorted by the scan of the T1 table. A quick look at its properties confirms that:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Forward_Scan_Iterator_Properties.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Forward_Scan_Iterator_Properties.png\" alt=\"Forward Scan Iterator Properties\" title=\"Forward Scan Iterator Properties\" width=\"263\" height=\"389\" class=\"aligncenter size-full wp-image-934\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Forward_Scan_Iterator_Properties.png 263w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Forward_Scan_Iterator_Properties-202x300.png 202w\" sizes=\"auto, (max-width: 263px) 100vw, 263px\" \/><\/a>\n<\/p>\n<p>\nThis scan is a forward scan, as both <span class=\"tt\">ORDER BY<\/span> statements  are asking to sort by Id ascending. To make this scan go backwards we should just have to change the query to sort by Id descending in both places:\n<\/p>\n<div>\n[sql]\nSELECT  *<br \/>\nFROM    dbo.T1 A<br \/>\n        INNER JOIN ( SELECT TOP ( 1000000 )<br \/>\n                            B.*<br \/>\n                     FROM   dbo.T2 B<br \/>\n                            INNER JOIN dbo.T2 C ON B.v1 = C.v1<br \/>\n                     ORDER BY B.Id DESC<br \/>\n                   ) BC ON A.Id = BC.Id<br \/>\nORDER BY A.Id DESC;<br \/>\n[\/sql]\n<\/div>\n<p>\n However, this query produces this rather unexpected plan:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backwards_Scan_avoidance_with_Loop_Join.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backwards_Scan_avoidance_with_Loop_Join.png\" alt=\"Backward Scan avoidance with Loop Join\" title=\"Backward Scan avoidance with Loop Join\" width=\"1110\" height=\"164\" class=\"aligncenter size-full wp-image-933\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backwards_Scan_avoidance_with_Loop_Join.png 1110w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backwards_Scan_avoidance_with_Loop_Join-300x44.png 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backwards_Scan_avoidance_with_Loop_Join-1024x151.png 1024w\" sizes=\"auto, (max-width: 1110px) 100vw, 1110px\" \/><\/a>\n<\/p>\n<p>\nA loop join with an index seek against the T1 table to retrieve 1,000,000 single rows &ndash; that cannot be good.\n<\/p>\n<p>\nBefore we look at execution statistics let's force the merge join back by specifying a join hint:\n<\/p>\n<div>\n[sql]\nSELECT  *<br \/>\nFROM    dbo.T1 A<br \/>\n        INNER MERGE JOIN ( SELECT TOP ( 1000000 )<br \/>\n                                  B.*<br \/>\n                           FROM   dbo.T2 B<br \/>\n                                  INNER JOIN dbo.T2 C ON B.v1 = C.v1<br \/>\n                           ORDER BY B.Id DESC<br \/>\n                         ) BC ON A.Id = BC.Id<br \/>\nORDER BY A.Id DESC;<br \/>\n[\/sql]\n<\/div>\n<p>\n Now we get the expected plan again:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Merge_Join_encouraged_Backward_Scan.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Merge_Join_encouraged_Backward_Scan.png\" alt=\"Merge Join encouraged Backward Scan\" title=\"Merge Join encouraged Backward Scan\" width=\"1117\" height=\"250\" class=\"aligncenter size-full wp-image-936\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Merge_Join_encouraged_Backward_Scan.png 1117w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Merge_Join_encouraged_Backward_Scan-300x67.png 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Merge_Join_encouraged_Backward_Scan-1024x229.png 1024w\" sizes=\"auto, (max-width: 1117px) 100vw, 1117px\" \/><\/a>\n<\/p>\n<p>\nIf you compare the properties for the iterators in the forward scan and the backward scan plan you will notice, that the cost of the two scan directions is not that much different:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backward_Scan_Iterator_properties.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backward_Scan_Iterator_properties.png\" alt=\"Backward Scan Iterator Properties\" title=\"Backward Scan Iterator Properties\" width=\"1082\" height=\"572\" class=\"aligncenter size-full wp-image-932\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backward_Scan_Iterator_properties.png 1082w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backward_Scan_Iterator_properties-300x158.png 300w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Backward_Scan_Iterator_properties-1024x541.png 1024w\" sizes=\"auto, (max-width: 1082px) 100vw, 1082px\" \/><\/a>\n<\/p>\n<p>\nThe estimated cost of the scan iterator is 0% in both cases. The bulk of the work is done in the hash self-join and the following sort of the T2 table.\n<\/p>\n<p>\nSo, let us take a look at the execution statistics of all three queries:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Query_Execution_Statistics.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Query_Execution_Statistics.png\" alt=\"Query Execution Statistics\" title=\"Query Execution Statistics\" width=\"656\" height=\"77\" class=\"aligncenter size-full wp-image-938\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Query_Execution_Statistics.png 656w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Query_Execution_Statistics-300x35.png 300w\" sizes=\"auto, (max-width: 656px) 100vw, 656px\" \/><\/a>\n<\/p>\n<p>\nThe execution statistics clearly show that the decision to go with a loop join was not necessarily the best. While the estimated cost for the backward scan is about 150% of the estimated cost for the loop join, the actual reads for the loop join version are about 3 million, which is more than 250 times higher than the 8000 reads for either scan direction.\n<\/p>\n<h3>Disk Access<\/h3>\n<p>\nTo understand were this dislike is coming from we need to look at the access pattern necessary to retrieve the data from disk. A forward scan of a table (or index), that is not heavily fragmented, looks pretty much like doing a single contiguous read of a big blob of data. SQL Server has a lot of performance optimizations build in that make this type of access as fast as possible. The Read-Ahead mechanism is a good example for that.\n<\/p>\n<p>\nA backward scan on the other hand looks quite the opposite: After reading a page, the disk has to do almost a complete turn to get to the previous page, which is the next one in line to be read. This is about the worst kind of random access you can come by.\n<\/p>\n<p>\nAs SQL Server always assumes that none of the requested pages are in cache, the decision to not get into that backward spinning game seems quite understandable.\n<\/p>\n<p>\nAlso, if you closely compare the two \"scanning\" execution plans you will notice that while the forward scan iterator is parallelized, the backward scan operator is executed single threaded. This is a general rule: SQL Server cannot execute a backward scan in parallel. That makes sense as with all that waiting for the disk to do another spin to get to the \"next\" page, it is unlikely for the data to come in quickly enough to keep multiple threads busy.\n<\/p>\n<h3>Estimates?<\/h3>\n<p>\nBut wait, there is one more thing: If you look at the image above and compare the properties of all iterators in the two scanning plans, you will notice something odd. The estimated CPU cost of the \"hash match inner join\" iterator goes from 11 in the \"forward\" case to 1357 in the \"backward\" case; the estimated IO cost makes a similar jump from 0 to 1654. That seems to not make a lot of sense, as the next iterator, the sort, is a blocking iterator. \"Blocking\" means that the iterator reads in <u>all<\/u> input rows into a holding area before producing any output rows. This implies that anything on the left side of a sort should not be able to influence the cost of operators on the right side of it. That is, unless it affects the number of rows significantly, as this is a TOP N Sort. See <a href=\"http:\/\/sqlity.net\/en\/908\/top-n-sort-a-little-bit-of-sorting\/\"> TOP N Sort \u2013 A Little Bit of Sorting <\/a> for an explanation. But as in this example all columns are \"mostly\" unique, the optimizer guesses correctly that about one million rows get passed into the hash join on each input and also about one million rows come out the other end. So row count estimates should not matter here.\n<\/p>\n<p>\nIf you look at the estimates when executing just that inner query sorting backwards, you will see that they exactly match the ones in the imbedded forward sorting case:\n<\/p>\n<p>\n<a href=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Iterator_Properties_for_Inner_Select.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Iterator_Properties_for_Inner_Select.png\" alt=\"Iterator Properties for Inner Select\" title=\"Iterator Properties for Inner Select\" width=\"994\" height=\"353\" class=\"aligncenter size-full wp-image-935\" srcset=\"https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Iterator_Properties_for_Inner_Select.png 994w, https:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Iterator_Properties_for_Inner_Select-300x106.png 300w\" sizes=\"auto, (max-width: 994px) 100vw, 994px\" \/><\/a>\n<\/p>\n<p>\nThat means that the scan direction change of the T1 table causes the estimates on the other side of the merge join to get completely thrown off.\n<\/p>\n<h3>Conclusion<\/h3>\n<p>\nSQL Servers dislike of backward scan operations is understandable when looking at the work necessary to retrieve the records from disk in opposite index order. Additionally, a backward scan cannot be executed in parallel. That adds to the list of reasons, why the backward scan seems unloved.\n<\/p>\n<p>\nHowever, the main reason why SQL Server avoids backward scans seems to be that they throw its cost estimations off, making following iterators appear a lot more expensive than they really are.\n<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\nWhen a query requires rows to be sorted, either directly requested with an [tt]ORDER BY[\/tt] clause or because one of the iterators requires it, SQL Server has two options to guarantee that order. The obvious one is to utilize a sort iterator. If the data comes from an index (clustered or covering), SQL Server can also use an &#8220;Ordered Scan&#8221; of the data. Depending on the requested sort direction, such an ordered scan can be either forward or backward.\n<\/p>\n<p>\nThis would hardly be worth an article, if there wasn&#8217;t the peculiarity that SQL Server obviously does not like the idea of having to execute an ordered scan that is directed backwards.\n<\/p>\n<p> <a href=\"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/\">[more&#8230;]<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[5,19,14],"tags":[],"class_list":["post-930","post","type-post","status-publish","format-standard","hentry","category-general","category-performance","category-sql-server-internals"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The Unloved Backward Scan - sqlity.net<\/title>\n<meta name=\"description\" content=\"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The Unloved Backward Scan - sqlity.net\" \/>\n<meta property=\"og:description\" content=\"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/\" \/>\n<meta property=\"og:site_name\" content=\"sqlity.net\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/sqlity.net\" \/>\n<meta property=\"article:published_time\" content=\"2012-04-29T20:31:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-11-13T18:59:00+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png\" \/>\n<meta name=\"author\" content=\"Sebastian Meine\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@sqlity\" \/>\n<meta name=\"twitter:site\" content=\"@sqlity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sebastian Meine\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/\"},\"author\":{\"name\":\"Sebastian Meine\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"headline\":\"The Unloved Backward Scan\",\"datePublished\":\"2012-04-29T20:31:29+00:00\",\"dateModified\":\"2014-11-13T18:59:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/\"},\"wordCount\":1433,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/04\\\/Plan_with_Forward_Scan.png\",\"articleSection\":[\"General\",\"Performance\",\"SQL Server Internals\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/\",\"name\":\"The Unloved Backward Scan - sqlity.net\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/04\\\/Plan_with_Forward_Scan.png\",\"datePublished\":\"2012-04-29T20:31:29+00:00\",\"dateModified\":\"2014-11-13T18:59:00+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\"},\"description\":\"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#primaryimage\",\"url\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/04\\\/Plan_with_Forward_Scan.png\",\"contentUrl\":\"http:\\\/\\\/sqlity.net\\\/wp-content\\\/uploads\\\/2012\\\/04\\\/Plan_with_Forward_Scan.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/930\\\/the-unloved-backward-scan\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The Unloved Backward Scan\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/sqlity.net\\\/en\\\/\",\"name\":\"sqlity.net\",\"description\":\"Quality for SQL\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/sqlity.net\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/sqlity.net\\\/en\\\/#\\\/schema\\\/person\\\/bcffd8c572bc2f1bd10fdba80135e53c\",\"name\":\"Sebastian Meine\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g\",\"caption\":\"Sebastian Meine\"},\"sameAs\":[\"http:\\\/\\\/sqlity.net\",\"https:\\\/\\\/x.com\\\/sqlity\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The Unloved Backward Scan - sqlity.net","description":"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/","og_locale":"en_US","og_type":"article","og_title":"The Unloved Backward Scan - sqlity.net","og_description":"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026","og_url":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/","og_site_name":"sqlity.net","article_publisher":"https:\/\/www.facebook.com\/sqlity.net","article_published_time":"2012-04-29T20:31:29+00:00","article_modified_time":"2014-11-13T18:59:00+00:00","og_image":[{"url":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png","type":"","width":"","height":""}],"author":"Sebastian Meine","twitter_card":"summary_large_image","twitter_creator":"@sqlity","twitter_site":"@sqlity","twitter_misc":{"Written by":"Sebastian Meine","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#article","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/"},"author":{"name":"Sebastian Meine","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"headline":"The Unloved Backward Scan","datePublished":"2012-04-29T20:31:29+00:00","dateModified":"2014-11-13T18:59:00+00:00","mainEntityOfPage":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/"},"wordCount":1433,"commentCount":0,"image":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#primaryimage"},"thumbnailUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png","articleSection":["General","Performance","SQL Server Internals"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/","url":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/","name":"The Unloved Backward Scan - sqlity.net","isPartOf":{"@id":"https:\/\/sqlity.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#primaryimage"},"image":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#primaryimage"},"thumbnailUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png","datePublished":"2012-04-29T20:31:29+00:00","dateModified":"2014-11-13T18:59:00+00:00","author":{"@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c"},"description":"To guarantee row order, SQL Server can utilize an ordered scan reading forward or backward. However, SQL Server dislikes the backward scan\u2026","breadcrumb":{"@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#primaryimage","url":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png","contentUrl":"http:\/\/sqlity.net\/wp-content\/uploads\/2012\/04\/Plan_with_Forward_Scan.png"},{"@type":"BreadcrumbList","@id":"https:\/\/sqlity.net\/en\/930\/the-unloved-backward-scan\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sqlity.net\/en\/"},{"@type":"ListItem","position":2,"name":"The Unloved Backward Scan"}]},{"@type":"WebSite","@id":"https:\/\/sqlity.net\/en\/#website","url":"https:\/\/sqlity.net\/en\/","name":"sqlity.net","description":"Quality for SQL","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sqlity.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/sqlity.net\/en\/#\/schema\/person\/bcffd8c572bc2f1bd10fdba80135e53c","name":"Sebastian Meine","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4ab0a6d02dd494849a584a2c3c8bc3bdcef1d0aa5f87e98bf905dbdb9ad2ce3a?s=96&d=mm&r=g","caption":"Sebastian Meine"},"sameAs":["http:\/\/sqlity.net","https:\/\/x.com\/sqlity"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2wXuw-f0","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/930","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/comments?post=930"}],"version-history":[{"count":0,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/posts\/930\/revisions"}],"wp:attachment":[{"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/media?parent=930"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/categories?post=930"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sqlity.net\/en\/wp-json\/wp\/v2\/tags?post=930"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}