{"id":3614,"date":"2020-10-25T22:06:40","date_gmt":"2020-10-25T22:06:40","guid":{"rendered":"https:\/\/nenadnoveljic.com\/blog\/?p=3614"},"modified":"2020-10-25T22:06:43","modified_gmt":"2020-10-25T22:06:43","slug":"wrong-join-cardinality-extended-statistics","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/","title":{"rendered":"Wrong Join-Cardinality with Extended Statistics"},"content":{"rendered":"<h1>Multi-column join<\/h1>\n<p>There&#8217;s a boundary condition with extended statistics that leads the join cardinality calculation astray.<\/p>\n<p>I&#8217;ll be using the following model to show that:<\/p>\n<pre><code>drop table t1 ;\ndrop table t2 ;\n\ncreate table t1\n(\n  id1 integer,\n  id2 integer\n);\n\ninsert into t1 select 1, mod(rownum, 200)\n  from dual connect by level &lt;= 1e5 ;\ncommit ;\n\nexec dbms_stats.gather_table_stats(null, 't1');\n\ncreate table t2\n(\n  id1 integer,\n  id2 integer,\n  filter integer\n);\n\ninsert into t2 \n  select 1, rownum, \n  case when rownum &lt;= 400 then 1 else trunc(dbms_random.value(2,300)) end case\n  from dual connect by level &lt;= 2e5 ;\ncommit ;\n\nbegin\n  dbms_stats.gather_table_stats(\n    null, 't2', \n\tmethod_opt =&gt; 'FOR ALL COLUMNS SIZE 1 FOR COLUMNS SIZE 300 filter'\n  );\nend;\n\/\n<\/code><\/pre>\n<pre><code>select \/*+ gather_plan_statistics *\/ 1 \n  from t1, t2\n  where \n    t1.id1 = t2.id1 and t1.id2 = t2.id2\n    and t2.filter = 1 ;<\/code><\/pre>\n<p>The model above has the following characteristics:<\/p>\n<ul>\n<li>t1 and t2 are joined on the composite key id1,id2<\/li>\n<li>id1, the first column in the composite join key, is redundant in both tables &#8211; it&#8217;s always 1.<\/li>\n<li>The join doesn&#8217;t filter any rows from t1, because all filtered rows from t2 are matched in t1.<\/li>\n<\/ul>\n<h1>Selectivity<\/h1>\n<p>The cardinality estimate is fairly accurate:<\/p>\n<pre><code>----------------------------------------------------------------------------------------------------------------\n| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n----------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT   |      |      1 |        |  99500 |00:00:00.03 |    1683 |       |       |          |\n|*  1 |  HASH JOIN         |      |      1 |    <span style=\"color:blue\">100K<\/span>|  <span style=\"color:blue\">99500<\/span> |00:00:00.03 |    1683 |  2078K|  2078K| 1530K (0)|\n|*  2 |   TABLE ACCESS FULL| T2   |      1 |    400 |    400 |00:00:00.01 |     499 |       |       |          |\n|   3 |   TABLE ACCESS FULL| T1   |      1 |    100K|    100K|00:00:00.01 |    1184 |       |       |          |\n----------------------------------------------------------------------------------------------------------------<\/code><\/pre>\n<p>The optimizer used the following selectivity:<\/p>\n<pre><code><span style=\"color:blue\">Join Card:  100000.000000<\/span> = outer (100000.000000) * inner (400.000000) * <span style=\"color:blue\">sel (0.002500)<\/span><\/code><\/pre>\n<p>The standard join selectivity formula (for not nulls) is:<\/p>\n<p>sel = 1\/greater(NDV(t1.id1,t1.id2),NDV(t2.id1,t2.id1))<\/p>\n<pre><code>set linesize 100\ncolumn table_name format a3\ncolumn column_name format a30\ncolumn density format 9.9000EEEE\nselect table_name, column_name, num_distinct, density from user_tab_cols \n  where table_name in ('T1','T2') order by table_name, column_name ;\n  \nTAB COLUMN_NAME                    NUM_DISTINCT      DENSITY\n--- ------------------------------ ------------ ------------\nT1  ID1                                       1   5.0775E-06\nT1  ID2                                     200   5.0000E-06\nT2  FILTER                                  299   3.2890E-03\nT2  ID1                                       1   2.5378E-06\nT2  ID2                                  200000   5.0000E-06<\/code><\/pre>\n<p>Since NDV(t1.id1) = NDV(t2.id1) = 1, the selectivity becomes:<\/p>\n<p>sel = 1\/greater(NDV(t1.id2),NDV(t2.id2)) <a href=\"https:\/\/www.apress.com\/gp\/book\/9781590596364\">[1]<\/a><\/p>\n<p>Further, because of the filter on t2, NDV(t2.id2) is the NDV of the filtered result set (not the total NDV). Note that there are no statistics for a filtered NDV. Optimizer derives it from the total NDV and the density of the filter predicate, by using the calculation for the statistical problem known as &#8220;sampling without replacement&#8221;. <a href=\"https:\/\/www.adellera.it\/static_html\/investigations\/select_without_replacement\/SelectWithoutReplacement.pdf\">[2]<\/a><\/p>\n<p>We can see the result of that calculation by observing the cardinality estimate of the following query:<\/p>\n<pre><code>select distinct id2 from t2 where filter = 1 ;\n\n-----------------------------------------------------------------------\n| Id  | Operation          | Name | E-Rows |  OMem |  1Mem | Used-Mem |\n-----------------------------------------------------------------------\n|   0 | SELECT STATEMENT   |      |        |       |       |          |\n|   1 |  HASH UNIQUE       |      |    <span style=\"color:blue\">400<\/span> |  2170K|  2170K| 1421K (0)|\n|*  2 |   TABLE ACCESS FULL| T2   |    400 |       |       |          |\n-----------------------------------------------------------------------<\/code><\/pre>\n<p>This number indeed matches with the value recorded in the optimizer trace: 1\/<span style=\"color:blue\">400<\/span> = <span style=\"color:blue\">0.0025<\/span><\/p>\n<h1>Extended statistics<\/h1>\n<p>Extended statistics on t2(id1,id2) shouldn&#8217;t change anything, because NDV(id1) * NDV(id2)  = NDV(id1,id2). But the estimated cardinality declined by orders of magnitude after creating them:<\/p>\n<pre><code>select \n  dbms_stats.create_extended_stats( \n    ownname   =&gt; null, \n\ttabname   =&gt; 't2', \n\textension =&gt; '(id1, id2)' \n  ) from dual ;\n\nbegin\n  dbms_stats.gather_table_stats(\n    null, 't2', \n\tmethod_opt =&gt; 'FOR ALL COLUMNS SIZE 1 FOR COLUMNS SIZE 300 filter'\n  );\nend;\n\/<\/code><\/pre>\n<pre><code>----------------------------------------------------------------------------------------------------------------\n| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n----------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT   |      |      1 |        |  99500 |00:00:00.04 |    1683 |       |       |          |\n|*  1 |  HASH JOIN         |      |      1 |    <span style=\"color:red\">200<\/span> |  99500 |00:00:00.04 |    1683 |  2078K|  2078K| 1568K (0)|\n|*  2 |   TABLE ACCESS FULL| T2   |      1 |    400 |    400 |00:00:00.01 |     499 |       |       |          |\n|   3 |   TABLE ACCESS FULL| T1   |      1 |    100K|    100K|00:00:00.01 |    1184 |       |       |          |\n----------------------------------------------------------------------------------------------------------------<\/code><\/pre>\n<p>The selectivity slumped:<\/p>\n<pre><code>Join selectivity using 1 ColGroups: 5.0000e-06 (sel1 = 0.000000, sel2 = 0.000000)\n<span style=\"color:red\">Join Card:  200.000000<\/span> = outer (400.000000) * inner (100000.000000) * <span style=\"color:red\">sel (5.0000e-06)<\/span><\/code><\/pre>\n<p>All statistics are correct, but the selectivity calculation changed &#8211; it&#8217;s now calculated based on the total NDV instead of the filtered NDV.<\/p>\n<pre><code>TAB COLUMN_NAME                    NUM_DISTINCT      DENSITY\n--- ------------------------------ ------------ ------------\nT1  ID1                                       1   5.0775E-06\nT1  ID2                                     200   5.0000E-06\nT2  FILTER                                  299   3.2890E-03\nT2  ID1                                       1   2.5378E-06\nT2  ID2                                  200000   5.0000E-06\nT2  SYS_STU3RTXGYOX7NS$MIUDXQDMQ0C       200000   <span style=\"color:red\">5.0000E-06<\/span><\/code><\/pre>\n<p>The selectivity didn&#8217;t improve even after disabling the extended statistics:<\/p>\n<pre><code>alter session set \"_optimizer_enable_extended_stats\" = false ;<\/code><\/pre>\n<pre><code>Using concatenated index cardinality sanity check for table T2\nRevised join sel: 5.0000e-06 = 5.0000e-06 * (1\/200000.00) * (1\/5.0000e-06)\n<span style=\"color:red\">Join Card:  200.000000<\/span> = outer (400.000000) * inner (100000.000000) * <span style=\"color:red\">sel (5.0000e-06)<\/span><\/code><\/pre>\n<p>The entry &#8220;Using concatenated index cardinality sanity check for table T2&#8221; is misleading, as I haven&#8217;t created any indexes yet. Apparently, a sanity check kicked in to create some ad-hoc join selectivity, but this selectivity is still wrong.<\/p>\n<p>Then I disabled that sanity check too:<\/p>\n<pre><code>alter session set \"_optimizer_join_sel_sanity_check\" = false ;<\/code><\/pre>\n<p>The selectivity didn&#8217;t change either:<\/p>\n<pre><code><span style=\"color:red\">Join Card:  200.000000<\/span> = outer (400.000000) * inner (100000.000000) * <span style=\"color:red\">sel (5.0000e-06)<\/span><\/code><\/pre>\n<p>Since NDV(id2) = NDV(id1,id2) we don&#8217;t know which NDV the optimizer took.<\/p>\n<p>I manipulated the column statistics to find that out:<\/p>\n<pre><code>begin\n  DBMS_STATS.SET_COLUMN_STATS (\n    null, 't2', 'id2', \n     distcnt =&gt; <span style=\"color:red\">150000<\/span>\n  );\nend; \n\/\n\n\nTAB COLUMN_NAME                    NUM_DISTINCT      DENSITY\n--- ------------------------------ ------------ ------------\nT2  ID2                                  <span style=\"color:red\">150000   6.6667E-06<\/span>\nT2  SYS_STU3RTXGYOX7NS$MIUDXQDMQ0C       200000   5.0000E-06<\/code><\/pre>\n<p>It was the NDV(id2):<\/p>\n<pre><code>Join Card:  266.666667 = outer (400.000000) * inner (100000.000000) * <span style=\"color:red\">sel (6.6667e-06)<\/span><\/code><\/pre>\n<p>The optimizer didn&#8217;t use the filtered NDV, even after deactivating the extended statistics. In other words, a sole presence of extended statistics ruins the calculation. The behavior is the same if we create the unique index or the primary key instead of extended statistics.<\/p>\n<p>What can we do?<\/p>\n<h1>Solution<\/h1>\n<p>The solution is to create a matching extended statistics on the other table:<\/p>\n<pre><code>select \n  dbms_stats.create_extended_stats( \n    ownname   =&gt; null, \n\ttabname   =&gt; 't1', \n\textension =&gt; '(id1, id2)' \n  ) from dual ;\n\nexec dbms_stats.gather_table_stats(null, 't1');<\/code><\/pre>\n<pre><code><span style=\"color:blue\">Join Card:  100000.000000<\/span> = outer (100000.000000) * inner (400.000000) * <span style=\"color:blue\">sel (0.002500)<\/span><\/code><\/pre>\n<h1>Summary<\/h1>\n<p>In summary, for correct join cardinality calculation we need matching extended statistics (or indexes) on both tables. With extended statistics on only one table with a filter, the optimizer uses the total NDV instead of the filtered NDV. As a consequence, selectivity and cardinality will be massively underestimated.<\/p>\n<h1>References<\/h1>\n<ul>\n<li><a href=\"https:\/\/www.apress.com\/gp\/book\/9781590596364\">[1]<\/a> Jonathan Lewis, <i>Cost-Based Oracle Fundamentals.<\/i> 2006.<\/li>\n<li><a href=\"https:\/\/www.adellera.it\/static_html\/investigations\/select_without_replacement\/SelectWithoutReplacement.pdf\">[2]<\/a> Alberto Dell&#8217;Era, <i>SELECT WITHOUT REPLACEMENT.<\/i> 2007.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Wrong cardinality calculation for multi-column join with filter predicate and extended statistics <a href=\"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[11,5,18],"tags":[],"class_list":["post-3614","post","type-post","status-publish","format-standard","hentry","category-cost-based-optimizer","category-oracle","category-statistics"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Wrong Join-Cardinality with Extended Statistics - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Wrong Join-Cardinality with Extended Statistics - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-25T22:06:40+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-10-25T22:06:43+00:00\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\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\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Wrong Join-Cardinality with Extended Statistics\",\"datePublished\":\"2020-10-25T22:06:40+00:00\",\"dateModified\":\"2020-10-25T22:06:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/\"},\"wordCount\":502,\"commentCount\":0,\"articleSection\":[\"cost based optimizer\",\"Oracle\",\"Statistics\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/\",\"name\":\"Wrong Join-Cardinality with Extended Statistics - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"datePublished\":\"2020-10-25T22:06:40+00:00\",\"dateModified\":\"2020-10-25T22:06:43+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/wrong-join-cardinality-extended-statistics\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Wrong Join-Cardinality with Extended Statistics\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Wrong Join-Cardinality with Extended Statistics - All-round Database Topics","description":"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics","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:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/","og_locale":"en_US","og_type":"article","og_title":"Wrong Join-Cardinality with Extended Statistics - All-round Database Topics","og_description":"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics","og_url":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/","og_site_name":"All-round Database Topics","article_published_time":"2020-10-25T22:06:40+00:00","article_modified_time":"2020-10-25T22:06:43+00:00","author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Wrong Join-Cardinality with Extended Statistics","datePublished":"2020-10-25T22:06:40+00:00","dateModified":"2020-10-25T22:06:43+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/"},"wordCount":502,"commentCount":0,"articleSection":["cost based optimizer","Oracle","Statistics"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/","url":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/","name":"Wrong Join-Cardinality with Extended Statistics - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"datePublished":"2020-10-25T22:06:40+00:00","dateModified":"2020-10-25T22:06:43+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"Wrong cardinality calculation for multi-column join with filter predicate and extended statistics","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/wrong-join-cardinality-extended-statistics\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Wrong Join-Cardinality with Extended Statistics"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=3614"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3614\/revisions"}],"predecessor-version":[{"id":3627,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/3614\/revisions\/3627"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=3614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=3614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=3614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}