{"id":396,"date":"2008-04-16T20:54:35","date_gmt":"2008-04-16T20:54:35","guid":{"rendered":"\/blogs\/conor\/post\/Costing-and-Statistics-continued.aspx"},"modified":"2008-04-16T20:54:35","modified_gmt":"2008-04-16T20:54:35","slug":"costing-and-statistics-continued","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/","title":{"rendered":"Costing and Statistics, continued&#8230;"},"content":{"rendered":"<p>I started off tonight playing with the new page compression feature.&nbsp; So far I like it.&nbsp; I haven&#8217;t found something yet about which I want to post (which is code for &#8220;I&#8217;m still looking for the seams ;)&#8221;), but I have some other things you can try to learn a few things about how the SQL Server QP makes assumptions about various kinds of predicates in queries during cardinality estimations.<\/p>\n<p>So, you may or may not know much about how the SQL Server QP figures out what plans to run.&nbsp; For the uninitiated, it almost seems like some form of magic.&nbsp; In some ways, it is &#8211; it&#8217;s very powerful and poorly understood by many, and it usually requires very little effort by someone skilled in the area to make something amazing happen.&nbsp; SQL Server merely needs to make itself sparkle when I fix a query plan and I&#8217;m set for life :).<\/p>\n<p>In reality, SQL Server uses a cost-based optimizer, which means that it keeps track of all sorts of interesting statistical information, row counts, page counts, etc.&nbsp; It uses all of these in formulas to come up with numbers for each plan fragment and then it weighs the relative costs of all of these to pick a plan that has the &#8220;least cost&#8221;.&nbsp; That sounds nice and absolute until you get to go actually try to make that work, and then you are left with all sorts of nasty questions like:<\/p>\n<p>* What should the cost formulas be?<br \/>* Do the numbers need to differ based on the customer&#8217;s hardware? How do we calibrate all of this stuff?&nbsp; What do we do as machines get faster?<br \/>* How do I estimate how many rows are going to come back from one predicate in my WHERE clause or join in time less than running the query to figure it out?<br \/>* Same question when I have a bunch of preciates?<\/p>\n<p>Eventually, the QP has to make a set of assumptions so that they can come up with a plan in a reasonable amount of time, both because customers don&#8217;t like things to ever take time and because managers don&#8217;t like customers to tell them about how much time something should take..&nbsp; One assumption might be that, data is uniformly distributed over a data type&#8217;s possible values when you don&#8217;t have any better information.&nbsp; This can help make it possible to come up with solutions that work well most of the time.&nbsp; The problem is that estimates can be wrong, and that can cause the QP to come up with a different plan than had it had correct information to use when selecting the plan.<\/p>\n<p>So, I&#8217;ll show you an example here.&nbsp; To be clear, I&#8217;m not saying that this is something that is &#8220;broken&#8221;.&nbsp; This just exposes a place where 2 different assumptions rub up against each other in a way that will SEEM odd to the outside observer.&nbsp; When you consider the average customer use cases, these assumptions are not bad and work very well the vast majority of the time&#8230;<\/p>\n<p>To the example:<\/p>\n<pre><span style=\"color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;\"><span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">drop<\/span> <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">table<\/span> comp1\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">create<\/span> <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">table<\/span> comp1(col1 <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">int<\/span> <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">identity<\/span>, col3 <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">nvarchar<\/span>(3000))\r\n\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">declare<\/span> @i <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">int<\/span> \r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">set<\/span> @i=0\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">while<\/span> @i &lt; 70000\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">begin<\/span>\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">insert<\/span> <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">into<\/span> comp1 (col3) <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">values<\/span> (N<span style=\"color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;\">'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'<\/span>)\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">set<\/span> @i=@i+1\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">end<\/span><\/span><\/pre>\n<p>So I create a table with the same long string in it 70,000 times.&nbsp; <\/p>\n<p>Then I run a query with a where clause just to get some statistics created:<\/p>\n<pre><span style=\"color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;\"><span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">select<\/span>  * <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">from<\/span> comp1 <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">where<\/span> col3 <span style=\"color: Silver; background-color: transparent; font-family: Courier New; font-size: 11px;\">like<\/span> <span style=\"color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;\">'%4567890%'<\/span><br><span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">dbcc<\/span> show_statistics (<span style=\"color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;\">'comp1'<\/span>, col3)<br><br><\/span>Once we have all of this stuff, we can look at the estimates for two very similar queries:<span style=\"color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;\"><br><\/span><\/pre>\n<p><\/p>\n<pre><span style=\"color: Black; background-color: transparent; font-family: Courier New; font-size: 11px;\"><span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">select<\/span>  * <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">from<\/span> comp1 <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">where<\/span> col3 <span style=\"color: Silver; background-color: transparent; font-family: Courier New; font-size: 11px;\">like<\/span> <span style=\"color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;\">'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890%'<\/span>\r\n\r\n<span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">select<\/span>  * <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">from<\/span> comp1 <span style=\"color: Blue; background-color: transparent; font-family: Courier New; font-size: 11px;\">where<\/span> col3 <span style=\"color: Silver; background-color: transparent; font-family: Courier New; font-size: 11px;\">like<\/span> <span style=\"color: Red; background-color: transparent; font-family: Courier New; font-size: 11px;\">'%123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890%'<\/span><\/span><\/pre>\n<p>(one is LIKE &#8216;abc%&#8217;.&nbsp; The other is LIKE &#8216;%abc% where abc is the value we have inserted 70,000 times).<\/p>\n<p>So, both queries will return 70,000 rows.&nbsp; <\/p>\n<p>Well, the abc% pattern query estimates 70,000 rows (good!).&nbsp; The second query estimates 69.6985 rows.&nbsp; that&#8217;s a bit under ;).<\/p>\n<p>Let&#8217;s talk about this a bit more so you can understand why.&nbsp; In the first query, there is an exact string match against a column represented in the statistics histogram.&nbsp; So, the likely outcome is to take that cardinality count to determine the number of rows that will likely be returned from the query.&nbsp; In this case, we expect all rows to come back.<\/p>\n<p>In the second one, there is no mechanism to estimate the cardinality of ANY string of this size (SQL Server does have a feature that does smaller strings which is exposed as the &#8220;STRING INDEX&#8221; in the histogram, but you can&#8217;t see the details of this object in 2005 and I haven&#8217;t seen that change in 2008 either).&nbsp; So, for really large strings, it is left with&#8230; guessing.<\/p>\n<p>So, that 69.6985 number is an estimate that is partially based on the length of the string.&nbsp; Now, the QP could try to walk through each statitistics object and try to find substrings against any existing piece of statistical data and then try to adjust its estimate.&nbsp; In practice, though, the cost of doing that is expensive.&nbsp; The various statistics objects are run at different times and have different sample rates, so even then they will vary somewhat.&nbsp; Finally, for most cases it may just not impact the plan choice that much.&nbsp; Odds are, though, that this will bite at least one of my readers at some point.&nbsp; So, this is good to know &#8211; it can help you find that spot where the assumption in the QP is causing your query plan to be wrong.&nbsp; This is the sort of case where you will want to consider a query hint to help the QP out.<\/p>\n<p>There are more assumptions (and seams between them) in the cardinality estimation code.&nbsp; I&#8217;ll let you guys go hunt for them a bit to find them.<\/p>\n<p>Happy Querying!<br \/>Conor Cunningham<\/p>\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I started off tonight playing with the new page compression feature.&nbsp; So far I like it.&nbsp; I haven&#8217;t found something yet about which I want to post (which is code for &#8220;I&#8217;m still looking for the seams ;)&#8221;), but I have some other things you can try to learn a few things about how the [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-396","post","type-post","status-publish","format-standard","hentry","category-sql-server-2008"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Costing and Statistics, continued... - Conor Cunningham<\/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\/conor\/costing-and-statistics-continued\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Costing and Statistics, continued... - Conor Cunningham\" \/>\n<meta property=\"og:description\" content=\"I started off tonight playing with the new page compression feature.&nbsp; So far I like it.&nbsp; I haven&#8217;t found something yet about which I want to post (which is code for &#8220;I&#8217;m still looking for the seams ;)&#8221;), but I have some other things you can try to learn a few things about how the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/\" \/>\n<meta property=\"og:site_name\" content=\"Conor Cunningham\" \/>\n<meta property=\"article:published_time\" content=\"2008-04-16T20:54:35+00:00\" \/>\n<meta name=\"author\" content=\"Conor Cunningham\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Conor Cunningham\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/\",\"name\":\"Costing and Statistics, continued... - Conor Cunningham\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/#website\"},\"datePublished\":\"2008-04-16T20:54:35+00:00\",\"dateModified\":\"2008-04-16T20:54:35+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/f9106e03423de6b5157295891b8c3ae3\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Costing and Statistics, continued&#8230;\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/\",\"name\":\"Conor Cunningham\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/f9106e03423de6b5157295891b8c3ae3\",\"name\":\"Conor Cunningham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d9c37eff231ec89c1b244347d966860875eea8b55b366911d2694e8cd9913e57?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d9c37eff231ec89c1b244347d966860875eea8b55b366911d2694e8cd9913e57?s=96&d=mm&r=g\",\"caption\":\"Conor Cunningham\"},\"url\":\"https:\/\/www.sqlskills.com\/blogs\/conor\/author\/conor\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Costing and Statistics, continued... - Conor Cunningham","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\/conor\/costing-and-statistics-continued\/","og_locale":"en_US","og_type":"article","og_title":"Costing and Statistics, continued... - Conor Cunningham","og_description":"I started off tonight playing with the new page compression feature.&nbsp; So far I like it.&nbsp; I haven&#8217;t found something yet about which I want to post (which is code for &#8220;I&#8217;m still looking for the seams ;)&#8221;), but I have some other things you can try to learn a few things about how the [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/","og_site_name":"Conor Cunningham","article_published_time":"2008-04-16T20:54:35+00:00","author":"Conor Cunningham","twitter_misc":{"Written by":"Conor Cunningham","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/","url":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/","name":"Costing and Statistics, continued... - Conor Cunningham","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/#website"},"datePublished":"2008-04-16T20:54:35+00:00","dateModified":"2008-04-16T20:54:35+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/f9106e03423de6b5157295891b8c3ae3"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/costing-and-statistics-continued\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/conor\/"},{"@type":"ListItem","position":2,"name":"Costing and Statistics, continued&#8230;"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/conor\/","name":"Conor Cunningham","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/conor\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/f9106e03423de6b5157295891b8c3ae3","name":"Conor Cunningham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/conor\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d9c37eff231ec89c1b244347d966860875eea8b55b366911d2694e8cd9913e57?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d9c37eff231ec89c1b244347d966860875eea8b55b366911d2694e8cd9913e57?s=96&d=mm&r=g","caption":"Conor Cunningham"},"url":"https:\/\/www.sqlskills.com\/blogs\/conor\/author\/conor\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/posts\/396","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/comments?post=396"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/posts\/396\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/media?parent=396"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/categories?post=396"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/conor\/wp-json\/wp\/v2\/tags?post=396"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}