You are viewing the documentation for a prerelease version.

View Latest

ADVISE

  • Developer Preview
The ADVISE statement provides index recommendations to optimize query response time.

This is a Developer Preview feature, intended for development purposes only. Do not use this feature in production. No Enterprise Support is provided for Developer Preview features.

Refer to Developer Preview Mode for more information.

Purpose

The ADVISE statement invokes the index advisor to provide index recommendations for a single query. You can use the ADVISE statement with any of the following types of query:

The index advisor can recommend regular secondary indexes, partial indexes, and array indexes for the following predicates and conditions:

  • Predicates in the WHERE clause

  • Join conditions in the ON clause for INDEX JOIN, ANSI JOIN, ANSI NEST, INDEX NEST, and ANSI MERGE operations

  • Predicates of elements in an UNNEST array

  • Predicates with the ANY expression

  • Predicates of subqueries in the FROM clause

The index advisor also suggests covering indexes and covering array indexes for queries in a single keyspace, including JOIN operations, ANY expressions, and UNNEST predicates.

The index advisor checks the indexes currently used by the query. If the query is already using the recommended indexes, the index advisor informs you, and does not recommend an index unnecessarily. Similarly, if the query is already using the optimal covering index, the index advisor informs you, and does not recommend a covering index.

Prerequisites

To execute the ADVISE statement, you must have the privileges required for the N1QL statement for which you want advice. For more details about user roles, see Authorization.

Syntax

advise-index ::= ADVISE [ INDEX ] ( select | update | delete | merge )
'ADVISE' 'INDEX'? ( select | update | delete | merge )

The statement consists of the ADVISE keyword, and optionally the INDEX keyword, followed by the query for which you want index advice.

Usage

If you run the ADVISE statement in the Query Workbench, you must use the Table, JSON, or Tree link to see the result. You cannot use the Advice link in the Query Workbench to see the result of the ADVISE statement.

Return Value

The ADVISE statement returns an object with the following properties.

Name Description Schema

#operator
required

The name of the operator — in this case, Advise.

string

advice
required

An object giving advice returned by the operator.

query
required

The N1QL query used to generate the advice.

string

Advice

Name Description Schema

#operator
required

The name of the operator — in this case, IndexAdvice.

string

adviseinfo
required

An array of objects giving index information.

< Information > array

Information

Name Description Schema

current_indexes
required

An array of Index objects, each giving information about one of the indexes (primary or secondary) that is currently used by the query.

< Indexes > array

recommended_indexes
required

If the index advisor recommends any indexes, this is an object giving information about the recommended indexes.

If the index advisor cannot recommend any indexes, this is a string stating that there are no recommended indexes at this time.

Name Description Schema

covering_indexes
optional

If there are any recommended covering indexes, this is an array of Index objects, each giving information about one of the recommended covering indexes.

If there are no recommended covering indexes, this field does not appear.

< Indexes > array

indexes
required

An array of Index objects, each giving information about one of the recommended secondary indexes.

< Indexes > array

Indexes

Name Description Schema

index_statement
required

The N1QL command used to define the index.

string

index_status
optional

Information on the status of the index, stating whether the index is identical to the recommended index, or whether the index is an optimal covering index.

This field is only returned for current indexes. If the index is not identical to the recommended index, or if it is not an optimal covering index, this field does not appear.

string

recommending_rule
required

The rules used to generate the recommendation.

This field is only returned for recommended indexes, or for current indexes if they are identical to the recommended index.

string

Recommendation Rules

The index advisor recommends secondary indexes based on the query predicate, according to the following rules. The rules are listed below in priority order. Within each recommended index, if there is more than one index key, they are sorted according to the priority order of these rules.

Rule Description Recommendation
  1. Leading array index for UNNEST

The query uses a predicate which applies to individual elements in an unnested array.

Example: UNNEST schedule AS x WHERE x.day = 1

An array index, where the leading index key is an array expression indexing all elements in the unnested array.

  1. Equality

The query has a predicate with an equality expression.

Example: WHERE id = 10

A secondary index, where the index key is the field referenced by the predicate expression.

  1. IN predicates

The query has a predicate with an IN expression.

Example: WHERE id IN [10, 20]

A secondary index, where the index key is the field referenced by the predicate expression.

  1. Not less than / between / not greater than

The query has a predicate with a <=, BETWEEN, or >= expression.

Example: WHERE id >= 10

A secondary index, where the index key is the field referenced by the predicate expression.

  1. Less than / between / greater than

The query has a predicate with a <, BETWEEN, or > expression.

Example: WHERE id BETWEEN 10 AND 25

A secondary index, where the index key is the field referenced by the predicate expression.

  1. Array predicate

The query has a predicate with an ANY expression.

Example: WHERE ANY v IN schedule SATISFIES v.utc > "19:00" END

An array index, where the index key is an array expression recursively indexing all elements referenced by the predicate expression.

  1. Derived join filter as leading key

The query has a join, which is filtered using an ON clause on the left-hand side keyspace.

Example: FROM `travel-sample` r JOIN `travel-sample` a ON r.airlineid = META(a).id

A secondary index, where the leading index key is the field from the left-hand side keyspace in the ON clause.

  1. IS NOT NULL / MISSING / VALUED predicates

The query has a predicate with IS NOT NULL, IS NOT MISSING, or IS NOT VALUED.

Example: WHERE id IS NOT NULL

A secondary index, where the index key is the field referenced by the predicate expression.

  1. Functional predicates

The query contains an indexable function.

Example: WHERE LOWER(name) = "john"

A functional index, where the index key contains the function referenced by the predicate expression.

  1. Flavor for partial index

The query includes filters on a particular flavor of document.

Example: WHERE type = "hotel"

A partial index for that flavor of document.

Index Names

The index advisor suggests a name for each index it recommends, starting with adv_, followed by the DISTINCT or ALL keyword for array indexes if applicable, and including the names of the fields referenced in the index definition, separated by underscores — for example, adv_city_type_name. Some field names may be truncated if they are too long.

The names that the index advisor suggests are not guaranteed to be unique. You should check the suggested index names and change any that are duplicates.

Examples

Example 1. Recommended index only
ADVISE SELECT * FROM `travel-sample` a WHERE a.type = 'hotel' AND a.country = 'France';
Result
[
  {
    "#operator": "Advise",
    "advice": {
      "#operator": "IndexAdvice",
      "adviseinfo": [
        {
          "current_indexes": [
            {
              "index_statement": "CREATE INDEX def_type ON `travel-sample`(`type`)"
            }
          ],
          "recommended_indexes": {
            "indexes": [
              {
                "index_statement": "CREATE INDEX adv_country_type ON `travel-sample`(`country`) WHERE `type` = 'hotel'",
                "recommending_rule": "Index keys follow order of predicate types: 2. equality, 10. flavor for partial index."
              }
            ]
          }
        }
      ]
    },
    "query": "SELECT * FROM `travel-sample` a WHERE a.type = 'hotel' AND a.country = 'France';"
  }
]
Example 2. Recommended index and covering index
ADVISE SELECT airportname FROM `travel-sample` WHERE type = 'airport' AND geo.alt NOT BETWEEN 0 AND 100;
Result
[
  {
    "#operator": "Advise",
    "advice": {
      "#operator": "IndexAdvice",
      "adviseinfo": [
        {
          "current_indexes": [
            {
              "index_statement": "CREATE INDEX def_type ON `travel-sample`(`type`)"
            }
          ],
          "recommended_indexes": {
            "covering_indexes": [
              {
                "index_statement": "CREATE INDEX adv_geo_alt_type_airportname ON `travel-sample`(`geo`.`alt`,`airportname`) WHERE `type` = 'airport'"
              }
            ],
            "indexes": [
              {
                "index_statement": "CREATE INDEX adv_geo_alt_type ON `travel-sample`(`geo`.`alt`) WHERE `type` = 'airport'",
                "recommending_rule": "Index keys follow order of predicate types: 5. less than/between/greater than, 10. flavor for partial index."
              }
            ]
          }
        }
      ]
    },
    "query": "SELECT airportname FROM `travel-sample` WHERE type = 'airport' AND geo.alt NOT BETWEEN 0 AND 100;"
  }
]
Example 3. Current index is identical to the recommended index
ADVISE SELECT * FROM `travel-sample` WHERE type LIKE 'air%'or type LIKE 'rou%';
Result
[
  {
    "#operator": "Advise",
    "advice": {
      "#operator": "IndexAdvice",
      "adviseinfo": [
        {
          "current_indexes": [
            {
              "index_statement": "CREATE INDEX def_type ON `travel-sample`(`type`)",
              "index_status": "SAME TO THE INDEX WE CAN RECOMMEND",
              "recommending_rule": "Index keys follow order of predicate types: 4. not less than/between/not greater than."
            }
          ],
          "recommended_indexes": "No index recommendation at this time."
        }
      ]
    },
    "query": "SELECT * FROM `travel-sample` WHERE type LIKE 'air%'or type LIKE 'rou%';"
  }
]
Example 4. Current index is an optimal covering index
ADVISE SELECT type FROM `travel-sample` WHERE type LIKE 'air%'or type LIKE 'rou%';
Result
[
  {
    "#operator": "Advise",
    "advice": {
      "#operator": "IndexAdvice",
      "adviseinfo": [
        {
          "current_indexes": [
            {
              "index_statement": "CREATE INDEX def_type ON `travel-sample`(`type`)",
              "index_status": "THIS IS AN OPTIMAL COVERING INDEX."
            }
          ],
          "recommended_indexes": "No index recommendation at this time."
        }
      ]
    },
    "query": "SELECT type FROM `travel-sample` WHERE type LIKE 'air%'or type LIKE 'rou%';"
  }
]
Example 5. No index can be recommended
ADVISE SELECT * FROM `travel-sample` LIMIT 5;
Result
[
  {
    "#operator": "Advise",
    "advice": {
      "#operator": "IndexAdvice",
      "adviseinfo": [
        {
          "current_indexes": [
            {
              "index_statement": "CREATE PRIMARY INDEX def_primary ON `travel-sample`"
            }
          ],
          "recommended_indexes": "No index recommendation at this time."
        }
      ]
    },
    "query": "SELECT * FROM `travel-sample` LIMIT 5;"
  }
]