{"id":1727,"date":"2018-02-28T18:00:37","date_gmt":"2018-02-28T18:00:37","guid":{"rendered":"http:\/\/nenadnoveljic.com\/blog\/?p=1727"},"modified":"2021-09-02T15:24:44","modified_gmt":"2021-09-02T15:24:44","slug":"cardinality-estimation-minus-operator","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/","title":{"rendered":"Cardinality Estimation for &#8220;MINUS&#8221; Operator"},"content":{"rendered":"<p>In this blog post I&#8217;ll be writing about a little imperfection in the Oracle optimizer which revealed itself when MINUS set operator have been used in a subquery. What I mean by that is that the cardinalities might be hugely overestimated in such case. The example I&#8217;ll be using here is just a simplification of a production query which suffered from this problem.<\/p>\n<h1>Oracle<\/h1>\n<p>Firstly, I&#8217;ll create some tables and fill them with data:<\/p>\n<pre><code>create table t1 ( n1 number ) ;\ninsert into t1\n  select 1 \n    from dual connect by level &lt;=50000 ; \n    \ncreate table t2 ( n1 number ) ;\ninsert into t2\n  select 2\n    from dual connect by level &lt;=100000 ;\n\ncreate table t3 ( n1 number ) ;    \ninsert into t3\n  select level \n    from dual connect by level &lt;=150000 ;\n\ncommit ;\n\nexec dbms_stats.gather_table_stats( null, 'T1' ) ;\nexec dbms_stats.gather_table_stats( null, 'T2' ) ;\nexec dbms_stats.gather_table_stats( null, 'T3' ) ;<\/code><\/pre>\n<p>It&#8217;s worth noting that the n1 column of the table t3 is very selective while the same column in the tables t1 and t2 contains just a bunch of repeating values. Now, let&#8217;s take a look at the following query and its execution plan:<\/p>\n<pre><code>select \/*+ gather_plan_statistics *\/ * \nfrom t3 where n1 in (\n  select n1 from t1 \n  minus\n  select n1 from t2 \n) ;\n\n        N1\n----------\n         1\n\t\t \n-----------------------------------------------------------------------------------------------------------------------\n| Id  | Operation             | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n-----------------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT      |          |      1 |        |      1 |00:00:00.01 |     524 |       |       |          |\n|*  1 |  HASH JOIN            |          |      1 |  50000 |      1 |00:00:00.01 |     524 |  2545K|  2545K|  810K (0)|\n|   2 |   VIEW                | VW_NSO_1 |      1 |  50000 |      1 |00:00:00.01 |     275 |       |       |          |\n|   3 |    MINUS              |          |      1 |        |      1 |00:00:00.01 |     275 |       |       |          |\n|   4 |     <span style=\"color: #ff0000;\">SORT UNIQUE<\/span>       |          |      1 |  <span style=\"color: #ff0000;\">50000 |      1<\/span> |00:00:00.01 |      84 |  2048 |  2048 | 2048  (0)|\n|   5 |      TABLE ACCESS FULL| T1       |      1 |  50000 |  50000 |00:00:00.01 |      84 |       |       |          |\n|   6 |     SORT UNIQUE       |          |      1 |    100K|      1 |00:00:00.01 |     191 |  2048 |  2048 | 2048  (0)|\n|   7 |      TABLE ACCESS FULL| T2       |      1 |    100K|    100K|00:00:00.01 |     191 |       |       |          |\n|   8 |   TABLE ACCESS FULL   | T3       |      1 |    150K|    150K|00:00:00.01 |     249 |       |       |          |\n-----------------------------------------------------------------------------------------------------------------------<\/code><\/pre>\n<p>As you can see, the optimizer estimated that the subquery block with MINUS would return <span style=\"color: #ff0000;\">50&#8217;000<\/span> rows instead of just <span style=\"color: #ff0000;\">1<\/span>. Apparently, the NDV of t1.n1 was not used at all for estimating the number of rows that are going to be returned by the <span style=\"color: #ff0000;\">SORT UNIQUE<\/span> step.<\/p>\n<p>Therefore, I recommended introducing DISTINCT when selecting t1.n1 as a workaround in this case. After doing so, the optimizer immediately came up with much better cardinality estimates.<\/p>\n<p>For instance, we can see below a significant improvement of the estimated cardinality after adding <span style=\"color: #ff0000;\">DISTINCT<\/span> into the subquery:<\/p>\n<pre><code>select \/*+ gather_plan_statistics *\/ * \nfrom t3 where n1 in (\n  select <span style=\"color: #ff0000;\">distinct<\/span> n1 from t1 \n  minus\n  select n1 from t2 \n) ;\n\n-----------------------------------------------------------------------------------------------------------------------\n| Id  | Operation             | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n-----------------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT      |          |      1 |        |      1 |00:00:00.01 |     524 |       |       |          |\n|*  1 |  HASH JOIN            |          |      1 |      1 |      1 |00:00:00.01 |     524 |  2545K|  2545K|  808K (0)|\n|   2 |   VIEW                | VW_NSO_1 |      1 |      1 |      1 |00:00:00.01 |     275 |       |       |          |\n|   3 |    MINUS              |          |      1 |        |      1 |00:00:00.01 |     275 |       |       |          |\n|   4 |     SORT UNIQUE       |          |      1 |      <span style=\"color: #ff0000;\">1<\/span> |      1 |00:00:00.01 |      84 |  2048 |  2048 | 2048  (0)|\n|   5 |      TABLE ACCESS FULL| T1       |      1 |  50000 |  50000 |00:00:00.01 |      84 |       |       |          |\n|   6 |     SORT UNIQUE       |          |      1 |    100K|      1 |00:00:00.01 |     191 |  2048 |  2048 | 2048  (0)|\n|   7 |      TABLE ACCESS FULL| T2       |      1 |    100K|    100K|00:00:00.01 |     191 |       |       |          |\n|   8 |   TABLE ACCESS FULL   | T3       |      1 |    150K|    150K|00:00:00.01 |     249 |       |       |          |\n-----------------------------------------------------------------------------------------------------------------------<\/code><\/pre>\n<p>All releases I&#8217;ve tested with, i.e. 11.2, 12.1 and 12.2, have behaved in the same way.<\/p>\n<h1>SQL Server<\/h1>\n<p>Furthermore, I cross-checked the quality of the cardinality estimation in SQL Server.<\/p>\n<p>Firstly, here are the commands to create exactly the same data set:<\/p>\n<pre><code>create table t1 ( n1 integer ) ;\n\ninsert into t1 select top(50000)\n  1\nFROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2\nOPTION (MAXDOP 1);\n\ncreate table t2 ( n1 integer ) ;\n\ninsert into t2 select top(100000)\n  2\nFROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2\nOPTION (MAXDOP 1);\n\ncreate table t3 ( n1 integer ) ;\n\ninsert into t3 select top(150000)\n  ROW_NUMBER() OVER (ORDER BY s1.[object_id])\n  FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2\nOPTION (MAXDOP 1);<\/code><\/pre>\n<p>Secondly, the select has to be slightly changed. I mean the key word &#8220;minus&#8221; must be replaced with &#8220;except&#8221; in SQL Server:<\/p>\n<pre><code>select * \nfrom t3 where n1 in (\n  select n1 from t1 \n  except\n  select n1 from t2 \n) ;\n\nset showplan_all on\n\nEstimateRows\tStmtText\n1               select *   from t3 where n1 in (    select n1 from t1     except    select n1 from t2   ) ;\n1               |--Hash Match(Inner Join, HASH:([master].[dbo].[t1].[n1])=([master].[dbo].[t3].[n1]), RESIDUAL:([master].[dbo].[t3].[n1]=[master].[dbo].[t1].[n1]))\n1                 |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([master].[dbo].[t1].[n1]))\n<span style=\"color: #ff0000;\">1<\/span>                 |    |--<span style=\"color: #ff0000;\">Hash Match(Aggregate, HASH:([master].[dbo].[t1].[n1])<\/span>, RESIDUAL:([master].[dbo].[t1].[n1] = [master].[dbo].[t1].[n1]))\n50000             |    |    |--Table Scan(OBJECT:([master].[dbo].[t1]))\n1                 |    |--Top(TOP EXPRESSION:((1)))\n1\t              |         |--Table Scan(OBJECT:([master].[dbo].[t2]), WHERE:([master].[dbo].[t1].[n1] = [master].[dbo].[t2].[n1]))\n150000\t          |--Table Scan(OBJECT:([master].[dbo].[t3]))\n<\/code><\/pre>\n<p>Obviously, the estimation was perfect even without DISTINCT.<\/p>\n<p>Likewise, I conducted the test on multiple releases, in particular on SQL Server 2014 and 2016.<\/p>\n<h1>Conclusion<\/h1>\n<p>In summary, Oracle optimizer doesn&#8217;t seem to use columns statistics when calculating the cardinality of a result set returned by the MINUS operator. Consequently, cardinality mentioned might be massively overestimated which in turn can give rise to suboptimal execution plans. This is especially true when the first select of the MINUS operator returns a non-selective column. In such cases, SELECT DISTINCT in the subquery might be an appropriate workaround for obtaining more accurate estimation.<\/p>\n<p>In contrast, SQL Server optimizer produces excellent cardinality estimations event without DISTINCT.<\/p>\n<h1>Updates<\/h1>\n<h2>2nd March 2018 &#8211; set-join conversion (SJC)<\/h2>\n<p><a href=\"https:\/\/people.sap.com\/stefan.koehler\">Stefan Koehler<\/a> suggested using SJC transformation instead of adding a redundant DISTINCT into the subquery. SJC is transformation which converts a set operation to JOIN. The obvious advantage of this approach is that you wouldn&#8217;t need to change each and every query to get better execution plans. On the other hand, it doesn&#8217;t seem to be a widely used feature, so some caution and extensive testing are needed before rolling it out into production.<\/p>\n<p>If you decide to go with it, you&#8217;ll have to explicitly enable it by setting the hidden parameter, for instance:<\/p>\n<pre><code>alter session set \"_convert_set_to_join\" = true ;<\/code><\/pre>\n<p>We&#8217;ve got indeed the accurate estimate in our example after enabling SJC:<\/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 |        |      1 |00:00:00.05 |     527 |       |       |          |\n|*  1 |  HASH JOIN            |          |      1 |      1 |      1 |00:00:00.05 |     527 |  2545K|  2545K|  812K (0)|\n|   2 |   VIEW                | VW_NSO_1 |      1 |      1 |      1 |00:00:00.05 |     275 |       |       |          |\n|   3 |    HASH UNIQUE        |          |      1 |      <span style=\"color: #ff0000;\">1 |      1<\/span> |00:00:00.05 |     275 |  2442K|  2442K|  780K (0)|\n|*  4 |     HASH JOIN ANTI    |          |      1 |    500 |  50000 |00:00:00.05 |     275 |  3987K|  2659K| 4476K (0)|\n|   5 |      TABLE ACCESS FULL| T1       |      1 |  50000 |  50000 |00:00:00.01 |      84 |       |       |          |\n|   6 |      TABLE ACCESS FULL| T2       |      1 |    100K|    100K|00:00:00.01 |     191 |       |       |          |\n|   7 |   TABLE ACCESS FULL   | T3       |      1 |    150K|    150K|00:00:00.01 |     249 |       |       |          |\n-----------------------------------------------------------------------------------------------------------------------<\/code><\/pre>\n<h2>April 13, 2018 &#8211; Bug<\/h2>\n<p>A bug with the following reference was filed for this problem: 27853032 &#8211; IMPROVE CARDINALITY ESTIMATES FOR MINUS OPERATOR<\/p>\n<h2>September 2, 2021 &#8211; Oracle 21c<\/h2>\n<p>The problem hasn&#8217;t been fixed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mind inaccurate cardinality estimations when using MINUS operator in subqueries. <a href=\"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/\" 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":[21,11,5,17],"tags":[],"class_list":["post-1727","post","type-post","status-publish","format-standard","hentry","category-comparison-oracle-sql-server","category-cost-based-optimizer","category-oracle","category-sql-server"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cardinality Estimation for &quot;MINUS&quot; Operator - All-round Database Topics<\/title>\n<meta name=\"description\" content=\"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.\" \/>\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\/cardinality-estimation-minus-operator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cardinality Estimation for &quot;MINUS&quot; Operator - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-28T18:00:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-09-02T15:24:44+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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Cardinality Estimation for &#8220;MINUS&#8221; Operator\",\"datePublished\":\"2018-02-28T18:00:37+00:00\",\"dateModified\":\"2021-09-02T15:24:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/\"},\"wordCount\":543,\"commentCount\":1,\"articleSection\":[\"Comparison Oracle-SQL Server\",\"cost based optimizer\",\"Oracle\",\"SQL Server\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/\",\"name\":\"Cardinality Estimation for \\\"MINUS\\\" Operator - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"datePublished\":\"2018-02-28T18:00:37+00:00\",\"dateModified\":\"2021-09-02T15:24:44+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"description\":\"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/cardinality-estimation-minus-operator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cardinality Estimation for &#8220;MINUS&#8221; Operator\"}]},{\"@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":"Cardinality Estimation for \"MINUS\" Operator - All-round Database Topics","description":"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.","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\/cardinality-estimation-minus-operator\/","og_locale":"en_US","og_type":"article","og_title":"Cardinality Estimation for \"MINUS\" Operator - All-round Database Topics","og_description":"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.","og_url":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/","og_site_name":"All-round Database Topics","article_published_time":"2018-02-28T18:00:37+00:00","article_modified_time":"2021-09-02T15:24:44+00:00","author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Cardinality Estimation for &#8220;MINUS&#8221; Operator","datePublished":"2018-02-28T18:00:37+00:00","dateModified":"2021-09-02T15:24:44+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/"},"wordCount":543,"commentCount":1,"articleSection":["Comparison Oracle-SQL Server","cost based optimizer","Oracle","SQL Server"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/","url":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/","name":"Cardinality Estimation for \"MINUS\" Operator - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"datePublished":"2018-02-28T18:00:37+00:00","dateModified":"2021-09-02T15:24:44+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"description":"Mind inaccurate cardinality estimations when using MINUS operator in subqueries.","breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/cardinality-estimation-minus-operator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Cardinality Estimation for &#8220;MINUS&#8221; Operator"}]},{"@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\/1727","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=1727"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/1727\/revisions"}],"predecessor-version":[{"id":3902,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/1727\/revisions\/3902"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=1727"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=1727"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=1727"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}