{"id":4193,"date":"2017-11-16T00:00:26","date_gmt":"2017-11-16T08:00:26","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4193"},"modified":"2025-06-13T17:23:02","modified_gmt":"2025-06-14T00:23:02","slug":"database-indexing-best-practices","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/","title":{"rendered":"Database Indexing Best Practices"},"content":{"rendered":"<p><b>Prelude: What is Database Indexing?<\/b><\/p>\n<p><b>Asynchronous Indexing:<\/b><span style=\"font-weight: 400\"> Global Secondary Indexes in databases &#8212; Couchbase, for example &#8212; can be created, updated and deleted without impacting the reads and writes on the JSON documents in Data nodes. This means that index-specific inserts\/updates\/deletes happen asynchronously and workloads are isolated from the rest of the system.<\/span><\/p>\n<p><b>Understand query SLAs and create indexes suitably: <\/b><span style=\"font-weight: 400\">Indexes are directly related to the N1QL queries that are run. N1QL and GSI tango together. Indexes are meant to be steroids for N1QL queries, reducing latency costs and increasing throughput. Indexes also demand their own storage, but the risk of losing business due to slow(\/shoddy) customer engagement experience is higher than their associated cost. Also, indexes in most cases live outside the confines of an application, which helps in managing their lifecycle suitably.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Let\u2019s look at some database index best practices for delivering the best customer experiences.<\/span><\/p>\n<p><b>1. Run Index Service on its own set of nodes<\/b><\/p>\n<p><span style=\"font-weight: 400\">Though all services &#8212; data, query, index, search, etc. &#8212; in Couchbase can be run on all nodes, we recommend that individual workloads run on their own set of nodes. This affords workload isolation and independent scaling. Also, hardware can be apportioned suitably based on the nature of the workload. For example, indexes are generally memory-intensive and queries are CPU-intensive. You can have different hardware for these different services. Independent scalability for best computational capacity per service is achieved by the architectural nicety that Multidimensional-Scaling (MDS) offers us.<\/span><\/p>\n<div id=\"attachment_4196\" style=\"width: 666px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-4196\" class=\"wp-image-4196\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/11\/homogenous-300x69.png\" alt=\"\" width=\"656\" height=\"151\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-300x69.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-1024x237.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-768x178.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-1536x356.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-20x5.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous-1320x306.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous.png 1580w\" sizes=\"auto, (max-width: 656px) 100vw, 656px\" \/><p id=\"caption-attachment-4196\" class=\"wp-caption-text\">When all services are run on all available nodes<\/p><\/div>\n<div id=\"attachment_4197\" style=\"width: 663px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-4197\" class=\"wp-image-4197\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/11\/mds-300x103.png\" alt=\"\" width=\"653\" height=\"224\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-300x103.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-1024x350.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-768x263.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-1536x525.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-20x7.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds-1320x451.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/mds.png 1796w\" sizes=\"auto, (max-width: 653px) 100vw, 653px\" \/><p id=\"caption-attachment-4197\" class=\"wp-caption-text\">When individual Services are run on their own dedicated nodes<\/p><\/div>\n<p><b>2. Understand MOI vs Standard GSI:\u00a0<\/b><\/p>\n<p><span style=\"font-weight: 400\">Couchbase 5.0 introduced Plasma as a <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/plasma-storage-engine-gsi\/\"><span style=\"font-weight: 400\">new Storage Engine for GSI<\/span><\/a><span style=\"font-weight: 400\">. Plasma is the underlined storage engine when \u2018Standard Global Secondary\u2019 is chosen at the time of the Setup. \u00a0Both storage types have different characteristics. When the use-case demands that the entire index be memory resident(stricter SLAs, lower latencies + higher throughputs), then choose MOI. Standard GSI (Plasma) is extremely useful when the entire index cannot be memory resident, we call this as Data-Greater-Than-Memory (DGM) scenario; also, this is useful when memory costs are a factor in deciding the index type. While MOI might get into a pause mode when memory is completely used up (i.e, index updatations stop, though queries will be serviced), Plasma suitably spills over to disk and operates (and indexes in databases do get updated) with ease. In Couchbase 5.0, Plasma works well till 20% DGM scenarios (i.e, 20% of the index data is in memory); if the query accesses keys across both memory and disk, then there is suitable impact to query performance due to the obvious disk access while querying.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Due to the nature of being completely memory resident, MOI is generally much faster than Standard GSI (especially, the former ForestDB). As of now, it is not possible to have both types of indexing in the database reside in the same cluster.<\/span><\/p>\n<p><span style=\"font-weight: 400\">The following schematic explains the different index storage engines available and their high level features<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-4199 aligncenter\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/11\/gsi_storage_engine-300x114.png\" alt=\"\" width=\"758\" height=\"288\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-300x114.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-1024x390.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-768x293.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-1536x585.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-20x8.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine-1320x503.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/gsi_storage_engine.png 2000w\" sizes=\"auto, (max-width: 758px) 100vw, 758px\" \/><b>3. Use Index Replicas : <span style=\"font-weight: 400\">Replicas in GSI are active replicas, i.e. they serve the twin purpose of load balancing N1QL queries and also taking in the traffic if the other index replica fails.<\/span><\/b><\/p>\n<pre class=\"\">create index idx on bucket(field1) with {\u201cnum_replica\u201d: 2}<\/pre>\n<p><span style=\"font-weight: 400\"> \u00a0(or)<\/span><\/p>\n<pre class=\"\">create index idx on bucket(field1) with {\u201cnodes\u201d:[\u201c1.2.3.1:8091\u201d, \u201c1.2.3.2:8091\u201d, \u201c1.2.3.3:8091\u201d]}<\/pre>\n<p><span style=\"font-weight: 400\">Both copies of the index are automatically updated asynchronously as the updates to documents happen on the data nodes. Always have at least one replica, which in turn means that there be two index nodes at the minimum for servicing N1QL queries. Due to the support of swap rebalance in 5.0, if an index node goes down, and a new node is added back, then the topology is maintained. This is extremely helpful for scale-up\/down operations due to seasonalities in queries, when you want to move between larger nodes and smaller nodes.<\/span><\/p>\n<p><span style=\"font-weight: 400\">If already using equivalent indexes, transition to replicas. Read more about this process <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/transition-index-replicas\/\"><span style=\"font-weight: 400\">here<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><b>4. Indexes Variants<\/b><\/p>\n<p>GSI has different variants based on different use cases. These different variants were purpose built for the nature of the queries and hence it is extremely important to understand the behaviour of the queries and properly leverage these index variants.<\/p>\n<table>\n<tbody>\n<tr>\n<td><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/n1ql\/n1ql-language-reference\/createprimaryindex.html\"><span style=\"font-weight: 400\">Primary Index<\/span><\/a><\/td>\n<td><span style=\"font-weight: 400\">Functional Index<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Named Primary Index<\/span><\/td>\n<td><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/n1ql\/n1ql-language-reference\/indexing-arrays.html\"><span style=\"font-weight: 400\">Array Index<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Composite Index<\/span><\/td>\n<td><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/indexes\/covering-indexes.html\"><span style=\"font-weight: 400\">Covered Index<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">Partial Index<\/span><\/td>\n<td><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/n1ql\/n1ql-language-reference\/adaptive-indexing.html\"><span style=\"font-weight: 400\">Adaptive Index<\/span><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400\">Do check out <\/span><a href=\"https:\/\/dzone.com\/articles\/index-first-and-query-faster\"><span style=\"font-weight: 400\">this DZone Article<\/span><\/a><span style=\"font-weight: 400\"> and <\/span><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/performance\/indexing-and-query-perf.html\"><span style=\"font-weight: 400\">this documentation<\/span><\/a><span style=\"font-weight: 400\"> for more on the above.<\/span><\/p>\n<p><span style=\"font-weight: 400\">For a database index example, let\u2019s look at the Covered Index: this variant contains predicates and all attributes that were indexed in the definition, because of which additional hop to data nodes are avoided. Query latencies are significantly lowered.<\/span><\/p>\n<p><span style=\"font-weight: 400\">For example, if we have the following:<\/span><\/p>\n<pre class=\"\">CREATE INDEX `idx_ts_type_iata` ON `travel-sample`(`type`,`iata`);<\/pre>\n<p><span style=\"font-weight: 400\">And use the query:<\/span><\/p>\n<pre class=\"\">select iata from `travel-sample` where type=\"airline\" and iata = \"TQ\"<\/pre>\n<p><span style=\"font-weight: 400\">Then the Explain Plan will reveal that the query is being \u2018covered\u2019 by the index:<\/span><\/p>\n<pre class=\"\">\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n  { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"covers\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"cover ((`travel-sample`.`type`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"cover ((`travel-sample`.`iata`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"cover ((meta(`travel-sample`).`id`))\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n  ], \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n  \"index\": \"idx_ts_type_iata\",<\/pre>\n<p><span style=\"font-weight: 400\">And if we try to select \u2018all\u2019(by using \u2018select *\u2019) attributes:<\/span><\/p>\n<pre><span style=\"font-weight: 400\">select * from `travel-sample` where type=\"airline\" and iata = \"TQ\";<\/span><\/pre>\n<p><span style=\"font-weight: 400\">Then the EXPLAIN PLAN reveals that the query is not covered(missing \u2018covers\u2019 field) as the Query Service has to hop to Data Service to fetch all the attributes:<\/span><\/p>\n<pre class=\"\">\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n  { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    \"index\": \"idx_ts_type_iata\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    \"index_id\": \"240cf64d8c6ddce3\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n    \"index_projection\": {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"primary_key\": true \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     },<\/pre>\n<p>Similarly, Array Indexes were created mainly to help our customers query JSON data, wherein Arrays are very common. A detailed post on this coming soon!<\/p>\n<p><strong>5.\u00a0<\/strong><b>Avoid Primary Keys in Production<\/b><\/p>\n<p><span style=\"font-weight: 400\">Unexpected full primary scans are possible and any possibility of such occurrences should be removed by avoiding primary indexes altogether in Production. N1QL Index Selection is a rule based system for now that checks for a possible index that will satisfy the query, and if there is no such, then it resorts to using the Primary Index. Primary index has all the keys of the documents &#8212; hence, query will fetch all keys from the primary index and then hop to Data Service to fetch the documents and then apply filters. As you can see, this is a very expensive operation and should be avoided at all costs.<\/span><\/p>\n<p><span style=\"font-weight: 400\">If there are no Primary Indexes created, and the query is not able to find a matching index to serve the query, then the Query Service errors with the following message, which should help you in creating the required Secondary index:<\/span><\/p>\n<p><span style=\"font-weight: 400\">\u201c<\/span><i><span style=\"font-weight: 400\">No index available on keyspace travel-sample that matches your query. Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online<\/span><\/i><span style=\"font-weight: 400\">.\u201d<\/span><\/p>\n<p><span style=\"font-weight: 400\">Also, as an inherent indexing best practice, partitioning of primary indexes is not supported by Couchbase. Unlike in many RDBMSes, primary keys are optional in Couchbase.<\/span><\/p>\n<p><b>6. Use EXPLAIN Plans<\/b><\/p>\n<p>To validate if the N1QL query is indeed using the indexes created, check the <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/n1ql\/n1ql-language-reference\/explain.html\">EXPLAIN PLAN <\/a>results. In the Couchbase Admin Console, this can easily be obtained by pasting the query in the code editor and clicking on the \u2018Explain\u2019 button. Look out for the \u201c<b>#operator<\/b>\u201d and \u201c<b>index<\/b>\u201d attributes of the result to confirm the index usage. Documentation Link.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4211 size-medium_large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/11\/explain_plan-768x562.png\" alt=\"\" width=\"768\" height=\"562\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-768x562.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-300x220.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-1024x750.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-1536x1125.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-20x15.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan-1320x966.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/explain_plan.png 1598w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><b>7. Index by Predicate<\/b><\/p>\n<p>The WHERE clause in a query is called as the Predicate and the fields\/attributes selected in the SELECT clause is called as Projection. Indexes should always be created with the Predicate clause in mind. This is because Index Selection happens based on the leading key of the index present in the Predicate.<\/p>\n<p><span style=\"font-weight: 400\">For example, if we have the following index on 4 attributes:<\/span><\/p>\n<pre class=\"\">CREATE INDEX `idx_ts_type_iata_name_icao` ON `travel-sample`(`type`,`iata`, `name`,`icao`);<\/pre>\n<p><span style=\"font-weight: 400\">And fire the following query that actually skps the icao attribute while querying, the query engine is smart enough to know to use the above index for best query performance.<\/span><\/p>\n<pre class=\"\">select name from `travel-sample` where icao=\"MLA\" and type=\"airline\";<\/pre>\n<p><span style=\"font-weight: 400\">The index selected can be seen in the explain plan below. Note that the query becomes a Covering query, as \u2018name\u2019 despite not being in Predicate is in Projection, hence the hop to Data Service is avoided.<\/span><\/p>\n<pre class=\"\">\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n   { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"covers\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"cover ((`travel-sample`.`type`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"cover ((`travel-sample`.`iata`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"cover ((`travel-sample`.`name`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"cover ((`travel-sample`.`icao`))\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"cover ((meta(`travel-sample`).`id`))\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      ], \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      \"index\": \"idx_ts_type_iata_name_icao\",<\/pre>\n<p><b>8. Use a Leading Key to Force Index Selection<\/b><\/p>\n<p>An index is not automatically selected for a query if the predicate used in the query does not match the leading key of the index. If you happen to see that the EXPLAIN PLAN does not force any index to be selected then use \u2018IS NOT MISSING\u2019 or \u2018IS NOT NULL\u2019 clause to force the index to be selected.<\/p>\n<p><span style=\"font-weight: 400\">Fo<\/span><span style=\"font-weight: 400\">r example, either of the following queries:<\/span><\/p>\n<pre class=\"\">select count(1) from `travel-sample` where type IS NOT NULL; \r\nselect count(1) from `travel-sample` where type IS NOT MISSING;<\/pre>\n<p><span style=\"font-weight: 400\">will use the following index, as the leading key of the index is \u2018type\u2019:<\/span><\/p>\n<pre class=\"\">CREATE INDEX `idx_ts_type_iata` ON `travel-sample`(`type`,`iata`);<\/pre>\n<p><span style=\"font-weight: 400\">To choose only an already created INDEX, use the <\/span><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/n1ql\/n1ql-language-reference\/hints.html\"><span style=\"font-weight: 400\">USE INDEX<\/span><\/a><span style=\"font-weight: 400\"> directive as part of the N1QL query. This is helpful in cases wherein you know that the index mentioned in USE INDEX has better selectivity than the one chosen by N1QL Rule Based Optimizer:<\/span><\/p>\n<pre class=\"\">select count(1) from `travel-sample` USE INDEX (idx_ts_type_iata) where type=\"airline\";<\/pre>\n<p><b>9. Use Partial Indexes<\/b><\/p>\n<p><span style=\"font-weight: 400\">Sometimes, the predicate to be indexed on might not fit into one node due to size limitations. \u00a0GSI in Couchbase are not automatically partitioned for now. This mandates that the administrator creates Partial Indexes; N1QL queries are smart enough to choose the appropriate index based on the kind of predicate used in the query when partial indexes are present. <\/span><\/p>\n<p><span style=\"font-weight: 400\">For example, we create the following two indexes based on the name being in two different ranges:<\/span><\/p>\n<pre class=\"\">CREATE INDEX `idx_ts_name_ak` ON `travel-sample`(`name`) WHERE name BETWEEN \"A\" AND \"K\"; \r\nCREATE INDEX `idx_ts_name_kz` ON `travel-sample`(`name`) WHERE name BETWEEN \"K\" AND \"Z\";<\/pre>\n<p><span style=\"font-weight: 400\">Now, following queries will automatically choose the suitable index as is evidenced in the respective EXPLAIN PLANS:<\/span><\/p>\n<pre class=\"\">select * from `travel-sample` where name=\"Astraeus\"; \r\n\r\nEXPLAIN PLAN : \r\n\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n   { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"index\": \"idx_ts_name_ak\",<\/pre>\n<pre class=\"\">select * from `travel-sample` where name=\"Texas Wings\"; \r\n\r\nEXPLAIN PLAN : \r\n\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n  { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"index\": \"idx_ts_name_kz\",<\/pre>\n<p><span style=\"font-weight: 400\">Indexes are suitably chosen when using the LIKE clause in the predicate. <\/span><span style=\"font-weight: 400\">For example, let\u2019s say we want to get all names that sound like a French Name(starting with \u201cL\u2019\u201d):<\/span><\/p>\n<pre class=\"\">select * from `travel-sample` where name like \"L'%\";\r\nEXPLAIN PLAN : \r\n\"~children\": [ \u00a0\u00a0\u00a0\u00a0\u00a0\r\n  { \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"#operator\": \"IndexScan2\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     \"index\": \"idx_ts_name_kz\",<\/pre>\n<p><b>10. Consistency Options<\/b><\/p>\n<p><span style=\"font-weight: 400\">Due to its asynchronous nature, GSI in Couchbase are eventually consistent by default and as already mentioned, they are asynchronously updated. Though, using change feeds(DCP), we update indexes as quickly possible, it is very much possible that certain document mutations haven\u2019t been updated in the indexes. If the query semantics demand stricter data consistency, then Couchbase offers tunable consistency models at the time of querying.<\/span><\/p>\n<p><span style=\"font-weight: 400\">The three consistency options available in Couchbase are:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">scan_consistency=not_bounded<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">scan_consistency=at_plus<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">scan_consistency=request_plus<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">For more: <\/span><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/architecture\/querying-data-with-n1ql.html\"><span style=\"font-weight: 400\">Documentation Link<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">Though request_plus semantics enforce data integrity, there is an impact on performance as query latencies increase; query waits for the relevant index to catchup with the latest mutations before the data is returned. \u2018not_bounded\u2019 (the default consistency option) is the fastest of all 3 consistency options.<\/span><\/p>\n<p><b>11. Monitor Index Catchup<\/b><\/p>\n<p>Generally the index service catches up with document mutations very quickly so as to leave little to no user impact. But as an administrator, if you want to make sure that the document mutations (to be updated in the index) are as minimal as possible and do not keep increasing, then look at the \u2018items remaining\u2019 metric under the index name.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-4212 size-medium_large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/11\/items_remaining-768x349.png\" alt=\"\" width=\"768\" height=\"349\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining-768x349.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining-300x136.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining-1024x465.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining-20x9.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining-1320x599.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/items_remaining.png 1432w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/p>\n<p><b>12. Use Defer builds<\/b><\/p>\n<p><span style=\"font-weight: 400\">Defer builds offers a 2 stage process of creating indexes. It is recommended that Defer Builds be put to optimum use always, as the same change feed is used to create indexes on a node. If DEFER builds are not used, the change feed from the data nodes has to be accessed multiple times, leading to more data transfer across the network and a slightly increased load on the data nodes.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Example:<\/span><\/p>\n<pre class=\"\">CREATE INDEX `idx_ts_type_iata` ON `travel-sample`(`type`,`iata`) WITH { \"defer_build\":true }; \r\nBUILD INDEX ON `travel-sample`(`idx_ts_type_iata`);<\/pre>\n<p><span style=\"font-weight: 400\">For more on CREATE INDEX syntax, please refer to the <\/span><a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.0\/n1ql\/n1ql-language-reference\/createindex.html\"><span style=\"font-weight: 400\">Documentation<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><b>13. Avoid large keys to index<\/b><\/p>\n<p>Prior to 5.0, there was a limitation on the key size for indexes (maximum 4k). This limitation has been removed in 5.0. Note that indexes are meant for data access paths, hence the data model and query (with indexes) should be structured to get the necessary information in the shortest time. Though customers can have any number of fields in a composite index, the index key size also grows proportionally. \u00a0Really large key sizes might impact performance. As a general rule of thumb, prefer to have 1kB as the combined size of all fields in a composite index; and if that is not possible, refactor the queries suitably.<\/p>\n<p><b>14. USE KEYS, avoid indexes<\/b><\/p>\n<p>It is not necessary that all N1QL queries require indexes. If your N1QL queries can work independently of indexes, by directly querying the documents using keys, then the directive USE KEYS is helpful.<\/p>\n<p><span style=\"font-weight: 400\">For example:<\/span><\/p>\n<pre class=\"\">SELECT * FROM `travel-sample` USE KEYS [\"landmark_37588\"];<\/pre>\n<p><span style=\"font-weight: 400\">The resulting explain plan will show a KeyScan being performed(without any mention of an IndexScan):<\/span><\/p>\n<pre class=\"\">\"~children\": [\r\n \u00a0\u00a0\u00a0\u00a0\u00a0{\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"#operator\": \"KeyScan\", \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        \"keys\": \"[\\\"landmark_37588\\\"]\" \u00a0\u00a0\u00a0\u00a0\u00a0\r\n      }<\/pre>\n<p><span style=\"font-weight: 400\">This is more of a thing to know than a best practice, as USE KEYS does not use indexes for returning results from the query service. Though highly unlikely that customers can have only queries that always use USE KEYS, this can be helpful in the edge cases which mandates such behaviour.<\/span><\/p>\n<p>Long Post!! But, I hope this was helpful in understanding databases and indexes and how indexing in DBMS best practices can help you deliver superior customer experiences :)<\/p>\n<p>PS: An Overview of GSI and What&#8217;s New in Couchbase Server 5.0 :\u00a0https:\/\/www.youtube.com\/watch?v=OrC2gkm2OFA<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Prelude: What is Database Indexing? Asynchronous Indexing: Global Secondary Indexes in databases &#8212; Couchbase, for example &#8212; can be created, updated and deleted without impacting the reads and writes on the JSON documents in Data nodes. This means that index-specific [&hellip;]<\/p>\n","protected":false},"author":3013,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,1812],"tags":[1695,1505,1626,1641],"ppma_author":[9055],"class_list":["post-4193","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-n1ql-query","tag-gsi","tag-index","tag-index-managment","tag-secondary-indexing"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Database Indexing Best Practices &amp; Types of Examples<\/title>\n<meta name=\"description\" content=\"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.\" \/>\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\/database-indexing-best-practices\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Database Indexing Best Practices\" \/>\n<meta property=\"og:description\" content=\"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-11-16T08:00:26+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T00:23:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1580\" \/>\n\t<meta property=\"og:image:height\" content=\"366\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Venkat Subramanian, Product Manager\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@venkasub\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Venkat Subramanian, Product Manager\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\"},\"author\":{\"name\":\"Venkat Subramanian, Product Manager\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/0756e2347c2166a32f93f9a7e07e9f90\"},\"headline\":\"Database Indexing Best Practices\",\"datePublished\":\"2017-11-16T08:00:26+00:00\",\"dateModified\":\"2025-06-14T00:23:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\"},\"wordCount\":2099,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"GSI\",\"Index\",\"index managment\",\"Secondary Indexing\"],\"articleSection\":[\"Couchbase Server\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\",\"name\":\"Database Indexing Best Practices & Types of Examples\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-11-16T08:00:26+00:00\",\"dateModified\":\"2025-06-14T00:23:02+00:00\",\"description\":\"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Database Indexing Best Practices\"}]},{\"@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\/0756e2347c2166a32f93f9a7e07e9f90\",\"name\":\"Venkat Subramanian, Product Manager\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8f9acdf95e167a15007b71867fe87a9a\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/53cfc83eb606325239f7058417a02969ab8ff0106a374bcdcf5d78f9b749cccd?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/53cfc83eb606325239f7058417a02969ab8ff0106a374bcdcf5d78f9b749cccd?s=96&d=mm&r=g\",\"caption\":\"Venkat Subramanian, Product Manager\"},\"description\":\"Venkat dabbles in product development and product management and has been developing data\/analytics platforms &amp; products. Significant chunk of his experience has been with Oracle, where he transitioned from being an Engineer in Oracle\u2019s Enterprise Manager team to Product Manager for Oracle's BI\/Analytics suite of products. He has worked in startups in the past helping develop machine-learning\/NLP products and distributed decisioning systems. He lurks around at @venkasub.\",\"sameAs\":[\"https:\/\/x.com\/venkasub\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/venkatcouchbase-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Database Indexing Best Practices & Types of Examples","description":"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.","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\/database-indexing-best-practices\/","og_locale":"en_US","og_type":"article","og_title":"Database Indexing Best Practices","og_description":"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.","og_url":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-11-16T08:00:26+00:00","article_modified_time":"2025-06-14T00:23:02+00:00","og_image":[{"width":1580,"height":366,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/homogenous.png","type":"image\/png"}],"author":"Venkat Subramanian, Product Manager","twitter_card":"summary_large_image","twitter_creator":"@venkasub","twitter_misc":{"Written by":"Venkat Subramanian, Product Manager","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/"},"author":{"name":"Venkat Subramanian, Product Manager","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/0756e2347c2166a32f93f9a7e07e9f90"},"headline":"Database Indexing Best Practices","datePublished":"2017-11-16T08:00:26+00:00","dateModified":"2025-06-14T00:23:02+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/"},"wordCount":2099,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["GSI","Index","index managment","Secondary Indexing"],"articleSection":["Couchbase Server","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/","url":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/","name":"Database Indexing Best Practices & Types of Examples","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-11-16T08:00:26+00:00","dateModified":"2025-06-14T00:23:02+00:00","description":"What is database indexing? Couchbase is here to with examples of database index best practices for delivering a high-quality customer experience.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/database-indexing-best-practices\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Database Indexing Best Practices"}]},{"@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\/0756e2347c2166a32f93f9a7e07e9f90","name":"Venkat Subramanian, Product Manager","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8f9acdf95e167a15007b71867fe87a9a","url":"https:\/\/secure.gravatar.com\/avatar\/53cfc83eb606325239f7058417a02969ab8ff0106a374bcdcf5d78f9b749cccd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/53cfc83eb606325239f7058417a02969ab8ff0106a374bcdcf5d78f9b749cccd?s=96&d=mm&r=g","caption":"Venkat Subramanian, Product Manager"},"description":"Venkat dabbles in product development and product management and has been developing data\/analytics platforms &amp; products. Significant chunk of his experience has been with Oracle, where he transitioned from being an Engineer in Oracle\u2019s Enterprise Manager team to Product Manager for Oracle's BI\/Analytics suite of products. He has worked in startups in the past helping develop machine-learning\/NLP products and distributed decisioning systems. He lurks around at @venkasub.","sameAs":["https:\/\/x.com\/venkasub"],"url":"https:\/\/www.couchbase.com\/blog\/author\/venkatcouchbase-com\/"}]}},"authors":[{"term_id":9055,"user_id":3013,"is_guest":0,"slug":"venkatcouchbase-com","display_name":"Venkat Subramanian, Product Manager","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/53cfc83eb606325239f7058417a02969ab8ff0106a374bcdcf5d78f9b749cccd?s=96&d=mm&r=g","author_category":"","last_name":"Subramanian, Product Manager","first_name":"Venkat","job_title":"","user_url":"","description":"Venkat dabbles in product development and product management and has been developing data\/analytics platforms &amp; products. Significant chunk of his experience has been with Oracle, where he transitioned from being an Engineer in Oracle\u2019s Enterprise Manager team to Product Manager for Oracle's BI\/Analytics suite of products. He has worked in startups in the past helping develop machine-learning\/NLP products and distributed decisioning systems. He lurks around at @venkasub."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4193","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\/3013"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=4193"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4193\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=4193"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=4193"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=4193"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}