{"id":676,"date":"2008-09-06T11:23:00","date_gmt":"2008-09-06T11:23:00","guid":{"rendered":"\/blogs\/bobb\/post\/On-hinting-spatial-indexes-and-query-complexity.aspx"},"modified":"2013-01-03T23:59:48","modified_gmt":"2013-01-04T07:59:48","slug":"on-hinting-spatial-indexes-and-query-complexity","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/","title":{"rendered":"On hinting spatial indexes and query complexity"},"content":{"rendered":"<p>\n<span><font color=\"#000000\">After reading Isaac&#39;s recent&nbsp;<a href=\"http:\/\/blogs.msdn.com\/b\/isaac\/archive\/2008\/08\/29\/is-my-spatial-index-being-used.aspx\" class=\"broken_link\">blog posting about spatial queries and index hinting<\/a>, I thought I might add some information based on a query I was working with this week. Sometimes if you have a query that&#39;s too syntactically complex, hinting won&#39;t work. In these cases you can cause the index to be used (or at least hintable) by breaking up the query.<\/font><\/span><span><font color=\"#000000\">&nbsp;<\/font><\/span><span><font color=\"#000000\">Warning. Protracted code example follows.<\/font><\/span><span><font color=\"#000000\">&nbsp;<\/font><\/span>\n<\/p>\n<p>\n<span><\/span><font color=\"#000000\"><span>If the spatial query is somewhat complex, it&#39;s useful to write it out step by step, so we start with the query written out in steps. We&#39;re using three tables, a county table, highway table, and POI (points of interest) table. Without pondering the necessity of clipping to the county boundary twice, here&#39;s the original logic.<\/span><span><\/span><\/font><span><font color=\"#000000\">&nbsp;<\/font><\/span>\n<\/p>\n<p>\n<span>&#8211;Find all banks within 2km of I66 as it runs through Fairfax County <br \/>\nDECLARE @g geography <br \/>\nDECLARE @h geography <br \/>\nDECLARE @i geography <br \/>\nDECLARE @j geography <br \/>\nDECLARE @k geography <br \/>\nSELECT @g = geog from va where fips = 51059 &#8212; Fairfax County <br \/>\nSELECT @h = geog from us_hwys where route_num = &#39;I66&#39; &#8212; I66 Hwy <br \/>\nSELECT @i = @h.STIntersection(@g)&#8211; I66 within county <br \/>\nSELECT @j = @i.STBuffer(2000)&#8211; buffer around I66 <br \/>\nSELECT @k = @j.STIntersection(@g)&#8211; clip buffer to county boundary <br \/>\nSELECT geog from POI <br \/>\n&nbsp; WHERE geog.STIntersects(@k)=1 and Description = &#39;bank&#39; <\/span>\n<\/p>\n<p>\n<span>We thought that it might be better for the overall query performance to write this as a single SQL query, so, doing simple substitution, one subquery at a time, we come up with these two equivalent query sets at the end of the process:&nbsp;<\/span><span>&nbsp;<\/span>\n<\/p>\n<p>\n<span>&#8212; A. Almost there&#8230; 2-query process <br \/>\nDECLARE @k geography <br \/>\nselect @k = <br \/>\n((SELECT geog from us_hwys where route_num = &#39;I66&#39;).STIntersection( <br \/>\n&nbsp; (SELECT geog from va where fips = 51059) <br \/>\n)).STBuffer(2000).STIntersection( <br \/>\n&nbsp; (SELECT geog from va where fips = 51059) <br \/>\n) <br \/>\n&#8212; uses the spatial index without a hint, total elapsed time for both steps 2 seconds <br \/>\nSELECT geog from POI &#8212; with (index(spatial_idx_2)) <br \/>\nwhere geog.STIntersects(@k)=1 and Description = &#39;bank&#39; <br \/>\ngo <\/span>\n<\/p>\n<p>\n<span>&#8212; B. Done&#8230; 1 query <br \/>\n&#8212; But, doesn&#39;t use the spatial index <br \/>\n&#8212; Total elapsed time, 48 minutes 53 seconds! <br \/>\nSELECT geog from POI&nbsp; &#8212; with (index(spatial_idx_2))&nbsp; hint doesn&#39;t work <br \/>\nwhere geog.STIntersects( <br \/>\n&nbsp; ((SELECT geog from us_hwys where route_num = &#39;I66&#39;).STIntersection( <br \/>\n&nbsp;&nbsp;&nbsp; (SELECT geog from va where fips = 51059) <br \/>\n&nbsp; )).STBuffer(2000).STIntersection( <br \/>\n&nbsp;&nbsp;&nbsp; (SELECT geog from va where fips = 51059) <br \/>\n&nbsp; ) <br \/>\n)=1 and Description = &#39;bank&#39; <\/span>\n<\/p>\n<p>\n<span>The resulting query is too complex for the query processor to even &quot;think of&quot; a plan that uses the spatial index. Even hinting doesn&#39;t work. The simpler STIntersects query using the 2-query process can be hinted, but we don&#39;t need the hint. The query processor is smart enough to use the spatial index with the simplified version. Oh&#8230; <\/span>\n<\/p>\n<p>\n<span>So the moral of the story is not only to be on the lookout for index-hinting opportunities, but that sometimes, if the query is too complex the query processor won&#39;t take the hint. The error in this case was: <\/span>\n<\/p>\n<p>\n<span>Msg 8622, Level 16, State 1, Line 1 <br \/>\nQuery processor could not produce a query plan because of the hints defined in this query. <br \/>\nResubmit the query without specifying any hints and without using SET FORCEPLAN. <\/span>\n<\/p>\n<p>\n<span>In cases like this, it may be necessary to break the query into pieces in order to apply the hint. In this case, it happens with an STIntersects() that used four subqueries, the exact &quot;complexity point&quot; may vary with the query itself. <\/span>\n<\/p>\n<p>\n<span>Of course, in this case, because of the repeating &quot;clipping&quot; steps (clip to a particular county), we can rewrite the query to use common table expressions. This not only makes it easier to read but, by removing the redundant subquery, the query processor decides to use the index with the hint. <\/span>\n<\/p>\n<p>\n<span>WITH GetCounty as (SELECT geog from va where fips = N&#39;51059&#39;), <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp; GetHighway as(SELECT geog from us_hwys where route_num = &#39;I66&#39;) <br \/>\nSELECT POI.geog from POI with (index(spatial_idx_2)),&nbsp; GetCounty C,&nbsp; GetHighway H <br \/>\nWHERE POI.geog.STIntersects( <br \/>\n&nbsp; H.geog.STIntersection(C.geog).STBuffer(2000).STIntersection(C.geog) <br \/>\n)=1 and Description = &#39;bank&#39; <\/span>\n<\/p>\n<p style=\"margin: 0in 0in 0pt; line-height: normal\" class=\"MsoNormal\">\n<span><font color=\"#000000\">So watch out for introduction of excess complexity. Hope this was helpful.<\/font><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>After reading Isaac&#39;s recent&nbsp;blog posting about spatial queries and index hinting, I thought I might add some information based on a query I was working with this week. Sometimes if you have a query that&#39;s too syntactically complex, hinting won&#39;t work. In these cases you can cause the index to be used (or at least [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29,36],"tags":[],"class_list":["post-676","post","type-post","status-publish","format-standard","hentry","category-sql-server-2008","category-sql-server-spatial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>On hinting spatial indexes and query complexity - Bob Beauchemin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"On hinting spatial indexes and query complexity - Bob Beauchemin\" \/>\n<meta property=\"og:description\" content=\"After reading Isaac&#039;s recent&nbsp;blog posting about spatial queries and index hinting, I thought I might add some information based on a query I was working with this week. Sometimes if you have a query that&#039;s too syntactically complex, hinting won&#039;t work. In these cases you can cause the index to be used (or at least [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/\" \/>\n<meta property=\"og:site_name\" content=\"Bob Beauchemin\" \/>\n<meta property=\"article:published_time\" content=\"2008-09-06T11:23:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2013-01-04T07:59:48+00:00\" \/>\n<meta name=\"author\" content=\"Bob Beauchemin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bob Beauchemin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/\",\"name\":\"On hinting spatial indexes and query complexity - Bob Beauchemin\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\"},\"datePublished\":\"2008-09-06T11:23:00+00:00\",\"dateModified\":\"2013-01-04T07:59:48+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SQL Server 2008\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sql-server-2008\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"On hinting spatial indexes and query complexity\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\",\"name\":\"Bob Beauchemin\",\"description\":\"SQL Server Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\",\"name\":\"Bob Beauchemin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"caption\":\"Bob Beauchemin\"},\"sameAs\":[\"http:\/www.sqlskills.com\/blogs\/bobb\/\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"On hinting spatial indexes and query complexity - Bob Beauchemin","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:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/","og_locale":"en_US","og_type":"article","og_title":"On hinting spatial indexes and query complexity - Bob Beauchemin","og_description":"After reading Isaac&#39;s recent&nbsp;blog posting about spatial queries and index hinting, I thought I might add some information based on a query I was working with this week. Sometimes if you have a query that&#39;s too syntactically complex, hinting won&#39;t work. In these cases you can cause the index to be used (or at least [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/","og_site_name":"Bob Beauchemin","article_published_time":"2008-09-06T11:23:00+00:00","article_modified_time":"2013-01-04T07:59:48+00:00","author":"Bob Beauchemin","twitter_misc":{"Written by":"Bob Beauchemin","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/","name":"On hinting spatial indexes and query complexity - Bob Beauchemin","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website"},"datePublished":"2008-09-06T11:23:00+00:00","dateModified":"2013-01-04T07:59:48+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/on-hinting-spatial-indexes-and-query-complexity\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/"},{"@type":"ListItem","position":2,"name":"SQL Server 2008","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sql-server-2008\/"},{"@type":"ListItem","position":3,"name":"On hinting spatial indexes and query complexity"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/","name":"Bob Beauchemin","description":"SQL Server Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e","name":"Bob Beauchemin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","caption":"Bob Beauchemin"},"sameAs":["http:\/www.sqlskills.com\/blogs\/bobb\/"],"url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/comments?post=676"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/676\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/media?parent=676"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/categories?post=676"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/tags?post=676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}