Project: YugabyteDB (App Definition and Development / Database)
File: partial-index-ycql.md

title: Partial indexes in YugabyteDB YCQL headerTitle: Partial indexes linkTitle: Partial indexes description: Using Partial indexes in YCQL headContent: Explore partial indexes in YugabyteDB using YCQL menu: v2.18: identifier: partial-index-ycql parent: explore-indexes-constraints weight: 241 type: docs <ul class="nav nav-tabs-alt nav-tabs-yb"> <li > <a href="../partial-index-ysql/" class="nav-link"> <i class="icon-postgres" aria-hidden="true"></i> YSQL </a> </li> <li > <a href="../partial-index-ycql/" class="nav-link active"> <i class="icon-cassandra" aria-hidden="true"></i> YCQL </a> </li> </ul> Partial indexes allow you to improve query performance by reducing the index size. A smaller index is faster to scan, easier to maintain, and requires less storage. Partial indexing works by specifying the rows defined by a conditional expression (called the predicate of the partial index), typically in the `WHERE` clause of the table. Partial indexes can be `UNIQUE`. A UNIQUE partial index enforces the constraint that for each possible tuple of indexed columns, only one row that satisfies the `index_predicate` is allowed in the table. A partial index might not be chosen even if the implication holds in cases where there are better query plans. The logical implication holds if all sub-expressions of the `indexpredicate` are present as is in the `whereexpression`. For example, assume `whereexpression = A AND B AND C`, `indexpredicate1 = A AND B`, `indexpredicate2 = A AND B AND D`, `indexpredicate3 = A AND B AND C AND D`. Then `whereexpression` only implies `indexpredicate1`. Currently, valid mathematical implications are not taken into account when checking for logical implication. For example, even if `whereexpression = x > 5` and `indexpredicate = x > 4`, the `SELECT` query will not use the index for scanning. This is because the two sub-expressions `x > 5` and `x > 4`

```sql CREATE INDEX indexname ON tablename(column_list) WHERE condition; ``` {{% explore-setup-single %}} Create a keyspace and a table as follows: ```cql ycqlsh> CREATE KEYSPACE example; ycqlsh> USE example; ycqlsh:example> CREATE TABLE orders (customer_id INT, order_date TIMESTAMP, product JSONB, warehouse_id INT, amount DOUBLE, PRIMARY KEY ((customerid), orderdate)) WITH transactions = { 'enabled' : true }; ``` Create a partial index for the `warehouseid` column with the expression `WHERE warehouseid < 100` to be able to enable a faster scanning of rows on queries which will benefit from such a search criteria. ```cql ycqlsh:example> CREATE INDEX idx ON orders (warehouse_id) WHERE warehouse_id < 100; ``` When using a prepared statement, the logical implication check (to decide if a partial index is usable) will only consider those sub-expressions of `where_expression` that don't have dynamic parameters. This is because the query plan is decided before execution (when a statement is prepared). ```cql ycqlsh:example> EXPLAIN SELECT product FROM orders WHERE warehouseid < 100 AND orderdate >= ?; // Idx can be used ``` ```output QUERY PLAN Index Scan using temp.idx on temp.orders Filter: (orderdate >= :orderdate) ``` ```sql ycqlsh:example> EXPLAIN SELECT product FROM orders WHERE warehouseid < ? and orderdate >= ?; // Idx cannot be used ``` ```output QUERY PLAN -- Seq Scan on temp.orders Filter: (warehouseid < :warehouseid) AND (orderdate >= :orderdate) ``` Without partial indexes, many combinations of operators together on the same column in a `SELECT`'s where expression (for example, `WHERE v1 != NULL and v1 = 5`) are not allowed. ```sql ycqlsh:example> EXPLAIN SELECT product FROM orders WHERE warehouseid != NULL AND warehouseid = ?; ``` ```output SyntaxException: Invalid CQL Statement. Illogical condition for where clause EXPLAIN SELECT product from orders where warehouseid != NULL and warehouseid = ?; ^^^^^^^^^^^^ (ql error -12) ``` With a partial index that subsumes some clauses of the `SELECT`'s where expression, then two or more operators that would not otherwise be supported together are supported. ```sql ycqlsh:example> CREATE INDEX warehouseidx ON orders (warehouseid) WHERE warehouse_id != NULL; ycqlsh:example> EXPLAIN SELECT product FROM orders WHERE warehouseid != NULL AND warehouseid = ?; // warehouse_idx can be used ``` ```output QUERY PLAN Index Scan using temp.warehouse_idx on temp.orders Key Conditions: (warehouseid = :warehouseid) ``` For more details, refer to in the YCQL API documentation.