{"id":6792,"date":"2019-05-05T21:34:51","date_gmt":"2019-05-06T04:34:51","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=6792"},"modified":"2025-06-13T20:28:48","modified_gmt":"2025-06-14T03:28:48","slug":"query-optimization-in-nosql-couchbase-mongodb","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/","title":{"rendered":"Approaches to Query Optimization in NoSQL"},"content":{"rendered":"<blockquote><p>A man returned home after walking around the globe for eleven years.\u00a0 Next day, when he told his wife he&#8217;s going to the corner store, she asked him: &#8220;are you taking the short route or the long one?&#8221;.<\/p><\/blockquote>\n<p>Queries can be executed in many different ways.\u00a0 All paths lead to the same query result.\u00a0 The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Efficiency is measured in latency and throughput, depending on the workload.\u00a0 The cost of Memory, CPU, disk usage is added to the cost of a plan in a cost-based optimizer.<\/p>\n<p>Now, in most cases, a <a href=\"https:\/\/www.couchbase.com\/resources\/why-nosql\/\">NoSQL database<\/a> will have <a href=\"https:\/\/www.couchbase.com\/blog\/unreasonable-effectiveness-of-sql\/\">SQL-like query<\/a> language support. So, a good optimizer is mandatory. When you don\u2019t have a good optimizer, developers have to live with feature restrictions and DBAs have to live with NoSQL query performance issues.<\/p>\n<p><strong>Database Optimizer to Improve NoSQL Performance Searches<\/strong><\/p>\n<p>NosSQL query optimization allows you to choose an optimal index and access paths to execute the search. <span style=\"font-weight: 400\">At a very high level, SQL optimizers decide the following before creating the execution tree:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Query rewrite based on heuristics, cost or both.<\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Just like an editor removes unnecessary words from a writing, query rewrite work can range from eliminating unnecessary predicates to subquery flattening, converting appropriate LEFT OUTER JOINS to INNER JOINS, folding of derived tables, etc.<\/span><\/li>\n<\/ul>\n<\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Index selection.<\/span>\n<ul>\n<li style=\"font-weight: 400\">Selecting the optimal index(es) for each of the table (keyspaces in Couchbase N1QL, collection in case of MongoDB performance best practices)<\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Depending on the index selected, choose the predicates to push down, see the query is covered or not, decide on sort and pagination strategy.<\/span><\/li>\n<\/ul>\n<\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Join reordering <\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">(A INNER JOIN B INNER JOIN C) \u00a0is equivalent to (B INNER JOIN C INNER JOIN A). \u00a0The optimizer will have to determine the most optimal way to sequence these joins.<\/span><\/li>\n<\/ul>\n<\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Join type<\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Databases can implement multiple types of join algorithms: nested loop, hash, sort merge, zigzag, star (snowflake), etc. \u00a0Depending on the structure and cost, the optimizer will have to decide the type of join algorithm for each join operation.<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Consider the case of MongoDB restriction. <span style=\"font-weight: 400\">\u201c<\/span><span style=\"font-weight: 400\">A collection can have at most <\/span><b>one<\/b> <span style=\"font-weight: 400\">text<\/span><span style=\"font-weight: 400\"> index.\u201d\u00a0 <\/span><a href=\"https:\/\/docs.mongodb.com\/manual\/core\/index-text\/#restrictions\"><span style=\"font-weight: 400\">https:\/\/docs.mongodb.com\/manual\/core\/index-text\/#restrictions<\/span><\/a><span style=\"font-weight: 400\"> It documents a few other restrictions along with this. \u00a0For this article, explaining this one restriction will suffice.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-6794\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-300x65.png\" alt=\"\" width=\"733\" height=\"159\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-300x65.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-1024x223.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-768x167.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-1536x335.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-20x4.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM-1320x288.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/04\/Screen-Shot-2019-04-24-at-2.38.16-PM.png 1662w\" sizes=\"auto, (max-width: 733px) 100vw, 733px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><strong>Why should you care about this restriction?<\/strong><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">MongoDB and other NoSQL databases encourage you to denormalize (aggregate) your schema so you create a single large document representing an object: a customer, a partner, etc so the majority of your operations happen on a single (JSON) document. \u00a0So, a single customer document can contain customer information, customers orders, customer shipping information, customer billing information. <\/span>Having a single search index means, you need to create a single VERY LARGE index combining all the fields you\u2019d ever want to search. \u00a0Here\u2019s the problem: when you search for customer address, you don\u2019t want to see shipping address. When you search for shipping orderid, you don\u2019t want to see returned orderid.<\/li>\n<li style=\"font-weight: 400\">You can create multiple indexes on scalars in MongoDB. \u00a0Why the restriction on the text index?<\/li>\n<\/ol>\n<p><strong>Why does MongoDB Text Index is restricted to One index per Collection?\u00a0\u00a0<\/strong><\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li>Is it the number of the text indexes? Search indexes are typically built with an <a href=\"https:\/\/en.wikipedia.org\/wiki\/Inverted_index\">inverted-tree data structure<\/a>.\u00a0 But, <a href=\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\">MongoDB has chosen to build<\/a> it with the B-Tree index.\u00a0 This is unlikely to be the issue.<\/li>\n<li>Is it the size of the text indexes?\u00a0 Text indexes generated an array of tokens on text and indexes them.\u00a0 So, it&#8217;s an array index.\u00a0 Its size can grow exponentially when you use an array index. Size of the index increase linearly to the number of words indexes and not the number of documents.\u00a0 They may cause issues.<\/li>\n<li>Is it a problem with the optimizer?\u00a0 When you have multiple indexes, the optimizer will have to choose the right index for the query.\u00a0 If you restrict to one text index, choice easy. This is a symptom of a larger problem in MongoDB optimization techniques \u2014 It makes adhoc decisions resulting in restrictions like this.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">MongoDB\u2019s query plan language is simplistic, even if it\u2019s trying to <\/span><a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/sql-comparison\/\"><span style=\"font-weight: 400\">mimic the SQL operations.<\/span><\/a><span style=\"font-weight: 400\">.\u00a0 Let\u2019s see how MongoDB\u2019s query optimization tool handles these.<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Query rewrite: \u00a0<strong>Unsupported<\/strong>. MongoDB\u2019s queries are simplistic in find(), save(), remove(), update() methods. The aggregation pipeline is procedural and verbose. While it&#8217;s theoretically possible to rewrite, there\u2019s nothing in the documentation or plan to indicate any query rewrites.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Index selection: <strong>Supported<\/strong>. \u00a0MongoDB\u2019s optimizer tries to pick up a suitable index for each portion of the query and index can\/should be used. More on this below.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Join reordering: <strong>Unsupported<\/strong>. MongoDB\u2019s $lookup is part of the convoluted aggregation framework where the query is written like Unix pipeline, a procedural approach. \u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Join type selection: <strong>Unsupported<\/strong> since there\u2019s only one type join in MongoDB. \u00a0MongoDB has a\u00a0 constrained left outer join support via $lookup operator &#8212; arrays are unsupported in the join condition. \u00a0If you do use $lookup, the optimizer automatically uses the default join algorithm.\u00a0 There&#8217;s no mention of the type of join done.\u00a0\u00a0<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">Essentially, MongoDB query optimization only does index selection before creating the execution plan. But, query optimization in MongoDB seems to select the indexes an odd fashion \u2014 neither by rule not by statistics. \u00a0<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Pick a random index on one or more qualified index.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Use that plan if a subsequent query matches the query predicates, even if the constants, selectivities, and cardinalities are different.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Then at runtime, if the index scan returns more than 100 keys (!), runs each of the alternative plans to see which one returns the keys first. \u00a0At some point, it aborts the parallel execution and picks up one of them. It also replaces the plan in its plan cache.<\/span><\/li>\n<\/ol>\n<pre title=\"MongoDB Index Definition\" class=\"theme:github font-size:15 scroll:true whitespace-before:1 whitespace-after:1 lang:default decode:true\">Collection t1, with 3000 documenbts.\r\n\r\nCreate the following indexes:  Appendix 1 for the definition:\r\n\r\nMongoDB Enterprise &gt; db.t1.createIndex({x:1})\r\nMongoDB Enterprise &gt; db.t1.createIndex({y:1})\r\nMongoDB Enterprise &gt; db.t1.createIndex({x:1, y:1})\r\nMongoDB Enterprise &gt; db.t1.createIndex({y:1, x:1})\r\n\r\n<\/pre>\n<p>This is a single collection with 4 indexes on (x), (y), (x, y) and (y, x).\u00a0 Now, see this:<\/p>\n<pre class=\"theme:github font-size:15 wrap:true whitespace-before:1 whitespace-after:1 lang:js decode:true\">MongoDB Enterprise &gt; db.t1.find({x:{$gt:0}, y:99}).explain()\r\n{\r\n\t\"queryPlanner\" : {\r\n\t\t\"plannerVersion\" : 1,\r\n\t\t\"namespace\" : \"test.t1\",\r\n\t\t\"indexFilterSet\" : false,\r\n\t\t\"parsedQuery\" : {\r\n\t\t\t\"$and\" : [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"y\" : {\r\n\t\t\t\t\t\t\"$eq\" : 99\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"x\" : {\r\n\t\t\t\t\t\t\"$gt\" : 0\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t},\r\n\t\t\"winningPlan\" : {\r\n\t\t\t\"stage\" : \"FETCH\",\r\n\t\t\t\"filter\" : {\r\n\t\t\t\t\"x\" : {\r\n\t\t\t\t\t\"$gt\" : 0\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\t\"inputStage\" : {\r\n\t\t\t\t\"stage\" : \"IXSCAN\",\r\n\t\t\t\t\"keyPattern\" : {\r\n\t\t\t\t\t\"y\" : 1\r\n\t\t\t\t},\r\n\t\t\t\t\"indexName\" : \"y_1\",\r\n\t\t\t\t\"isMultiKey\" : false,\r\n\t\t\t\t\"multiKeyPaths\" : {\r\n\t\t\t\t\t\"y\" : [ ]\r\n\t\t\t\t},\r\n\t\t\t\t\"isUnique\" : false,\r\n\t\t\t\t\"isSparse\" : false,\r\n\t\t\t\t\"isPartial\" : false,\r\n\t\t\t\t\"indexVersion\" : 2,\r\n\t\t\t\t\"direction\" : \"forward\",\r\n\t\t\t\t\"indexBounds\" : {\r\n\t\t\t\t\t\"y\" : [\r\n\t\t\t\t\t\t\"[99.0, 99.0]\"\r\n\t\t\t\t\t]\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n<\/pre>\n<p>Even on this simple document structure, MongoDB selects the index on (y) even though there the query has filters on x and y: <strong>({x:{$gt:0}, y:99})<\/strong>.<\/p>\n<p>To manage all of these uncertainties and the performance issues it will lead to, MongoDB provides a <a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/method\/js-plan-cache\/\">number of APIs to manage the query plan cache<\/a>: flush specific cache entry, flush the whole plan cache.\u00a0 \u00a0Instead of developing applications, MongoDB developers &amp; DBAs, need to manage the plan cache.\u00a0 \u00a0Developers and DBAs don&#8217;t need to manage the plan cache in other enterprise databases.<\/p>\n<p>Back to the original question: <strong><em>Why you can\u2019t create multiple text indexes on MongoDB?<\/em><\/strong><\/p>\n<p>Building multiple indexes shouldn&#8217;t be an issue if they simply allowed it.\u00a0 The\u00a0<strong>real problem<\/strong> is that when you give a text predicate in your query,\u00a0 the MongoDB optimizer unable to choose the right index.\u00a0 It cannot validate these text indexes against the text predicate.\u00a0 MongoDB optimizer doesn&#8217;t follow a natural logic or a logical framework.\u00a0 \u00a0Hence the restriction.<\/p>\n<p><em>And, it could even hurt you!<\/em><\/p>\n<blockquote class=\"twitter-tweet\" data-lang=\"en\">\n<p dir=\"ltr\" lang=\"en\">I really like <a href=\"https:\/\/twitter.com\/hashtag\/MongoDB?src=hash&amp;ref_src=twsrc%5Etfw\">#MongoDB<\/a> but writing queries in JSON is painful (esp aggregation). It&#8217;s a curly brackets hell with poor tooling support. Same goes for <a href=\"https:\/\/twitter.com\/hashtag\/ElasticSearch?src=hash&amp;ref_src=twsrc%5Etfw\">#ElasticSearch<\/a>. Fortunately, due to Java\/Kotlin libraries, we rarely have to write them directly. But when we have to, it hurts.<\/p>\n<p>\u2014 Philipp Hauer (@philipp_hauer) <a href=\"https:\/\/twitter.com\/philipp_hauer\/status\/1118804630635515905?ref_src=twsrc%5Etfw\">April 18, 2019<\/a><\/p><\/blockquote>\n<p>Couchbase N1QL has added text index to N1QL for the upcoming release.\u00a0 See the details at <a href=\"https:\/\/www.couchbase.com\/blog\/n1ql-and-search-how-to-leverage-fts-index-in-n1ql-query\/\">https:\/\/www.couchbase.com\/blog\/n1ql-and-search-how-to-leverage-fts-index-in-n1ql-query\/<\/a>. Users can create any number of text indexes and the optimizer will choose a qualified (sargable) index and use it.\u00a0 It also supports searching during joins, post index scans, etc because the optimizer understands the search predicate and layers into its decision logic.\u00a0 There&#8217;s no new API, or new plan to manage. That&#8217;s the power of having Couchbase!<\/p>\n<h5 style=\"margin-bottom: 46.8359px\"><strong>Resources:<\/strong><\/h5>\n<ol>\n<li>An Overview of Query Optimization in Relational Systems: <a href=\"https:\/\/web.stanford.edu\/class\/cs345d-01\/rl\/chaudhuri98.pdf\">https:\/\/web.stanford.edu\/class\/cs345d-01\/rl\/chaudhuri98.pdf<\/a><\/li>\n<li>A Deep Dive Into Couchbase N1QL Query Optimization: <a href=\"https:\/\/dzone.com\/articles\/a-deep-dive-into-couchbase-n1ql-query-optimization\">https:\/\/dzone.com\/articles\/a-deep-dive-into-couchbase-n1ql-query-optimization<\/a><\/li>\n<li><a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/method\/js-plan-cache\/\"><span style=\"font-weight: 400\">https:\/\/docs.mongodb.com\/manual\/reference\/method\/js-plan-cache\/<\/span><\/a><\/li>\n<li><a href=\"https:\/\/docs.mongodb.com\/manual\/core\/query-plans\/\"><span style=\"font-weight: 400\">https:\/\/docs.mongodb.com\/manual\/core\/query-plans\/<\/span><\/a><\/li>\n<li><a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/method\/js-plan-cache\/\"><span style=\"font-weight: 400\">https:\/\/docs.mongodb.com\/manual\/reference\/method\/js-plan-cache\/<\/span><\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A man returned home after walking around the globe for eleven years.\u00a0 Next day, when he told his wife he&#8217;s going to the corner store, she asked him: &#8220;are you taking the short route or the long one?&#8221;. Queries can [&hellip;]<\/p>\n","protected":false},"author":55,"featured_media":4938,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,2165,1812],"tags":[1505,1261,1309,1725,1906],"ppma_author":[8929],"class_list":["post-6792","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-full-text-search","category-n1ql-query","tag-index","tag-json","tag-mongodb","tag-nosql-database","tag-optimizer"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Query Optimization in NoSQL and MongoDB Performance Plan<\/title>\n<meta name=\"description\" content=\"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.\" \/>\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.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Approaches to Query Optimization in NoSQL\" \/>\n<meta property=\"og:description\" content=\"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-05-06T04:34:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:28:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1388\" \/>\n\t<meta property=\"og:image:height\" content=\"744\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Keshav Murthy\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@rkeshavmurthy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Keshav Murthy\" \/>\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:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\"},\"author\":{\"name\":\"Keshav Murthy\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636\"},\"headline\":\"Approaches to Query Optimization in NoSQL\",\"datePublished\":\"2019-05-06T04:34:51+00:00\",\"dateModified\":\"2025-06-14T03:28:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\"},\"wordCount\":1365,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png\",\"keywords\":[\"Index\",\"JSON\",\"mongodb\",\"NoSQL Database\",\"Optimizer\"],\"articleSection\":[\"Couchbase Server\",\"Full-Text Search\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\",\"name\":\"Query Optimization in NoSQL and MongoDB Performance Plan\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png\",\"datePublished\":\"2019-05-06T04:34:51+00:00\",\"dateModified\":\"2025-06-14T03:28:48+00:00\",\"description\":\"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png\",\"width\":1388,\"height\":744},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Approaches to Query Optimization in NoSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636\",\"name\":\"Keshav Murthy\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4e51d72fc07c662aa791316deafffac4\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g\",\"caption\":\"Keshav Murthy\"},\"description\":\"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India, holds eleven US patents and has four US patents pending.\",\"sameAs\":[\"https:\/\/blog.planetnosql.com\/\",\"https:\/\/x.com\/rkeshavmurthy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/keshav-murthy\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Query Optimization in NoSQL and MongoDB Performance Plan","description":"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.","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.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/","og_locale":"en_US","og_type":"article","og_title":"Approaches to Query Optimization in NoSQL","og_description":"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.","og_url":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/","og_site_name":"The Couchbase Blog","article_published_time":"2019-05-06T04:34:51+00:00","article_modified_time":"2025-06-14T03:28:48+00:00","og_image":[{"width":1388,"height":744,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png","type":"image\/png"}],"author":"Keshav Murthy","twitter_card":"summary_large_image","twitter_creator":"@rkeshavmurthy","twitter_misc":{"Written by":"Keshav Murthy","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/"},"author":{"name":"Keshav Murthy","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636"},"headline":"Approaches to Query Optimization in NoSQL","datePublished":"2019-05-06T04:34:51+00:00","dateModified":"2025-06-14T03:28:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/"},"wordCount":1365,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png","keywords":["Index","JSON","mongodb","NoSQL Database","Optimizer"],"articleSection":["Couchbase Server","Full-Text Search","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/","url":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/","name":"Query Optimization in NoSQL and MongoDB Performance Plan","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png","datePublished":"2019-05-06T04:34:51+00:00","dateModified":"2025-06-14T03:28:48+00:00","description":"The NoSQL and query optimization tool evaluates the possibilities and selects the efficient plan. Find out what to do when you don\u2019t have a good optimizer.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/04\/Screen-Shot-2018-04-03-at-10.08.36-AM.png","width":1388,"height":744},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/query-optimization-in-nosql-couchbase-mongodb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Approaches to Query Optimization in NoSQL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636","name":"Keshav Murthy","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4e51d72fc07c662aa791316deafffac4","url":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","caption":"Keshav Murthy"},"description":"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India, holds eleven US patents and has four US patents pending.","sameAs":["https:\/\/blog.planetnosql.com\/","https:\/\/x.com\/rkeshavmurthy"],"url":"https:\/\/www.couchbase.com\/blog\/author\/keshav-murthy\/"}]}},"authors":[{"term_id":8929,"user_id":55,"is_guest":0,"slug":"keshav-murthy","display_name":"Keshav Murthy","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","author_category":"","last_name":"Murthy","first_name":"Keshav","job_title":"","user_url":"https:\/\/blog.planetnosql.com\/","description":"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India,  holds ten US patents and has three US patents pending."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/6792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=6792"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/6792\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/4938"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=6792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=6792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=6792"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=6792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}