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

title: Secondary indexes in YugabyteDB YCQL headerTitle: Secondary indexes linkTitle: Secondary indexes description: Overview of Secondary indexes in YCQL headContent: Explore secondary indexes in YugabyteDB using YCQL menu: v2.18: identifier: secondary-indexes-ycql parent: explore-indexes-constraints weight: 220 type: docs <ul class="nav nav-tabs-alt nav-tabs-yb"> <li > <a href="../secondary-indexes-ysql/" class="nav-link"> <i class="icon-postgres" aria-hidden="true"></i> YSQL </a> </li> <li > <a href="../secondary-indexes-ycql/" class="nav-link active"> <i class="icon-cassandra" aria-hidden="true"></i> YCQL </a> </li> </ul> Using indexes enhances database performance by enabling the database server to find rows faster. You can create, drop, and list indexes, as well as use indexes on expressions. You can create indexes in YCQL using the `CREATE INDEX` statement using the following syntax: ```sql CREATE INDEX indexname ON tablename(column_list); ``` YCQL supports , , , and secondary indexes. For more information, see . You can use the command to check the indexes as follows: ```cql DESCRIBE INDEX <index_name> ``` For more information, see . You can also use the `EXPLAIN` statement to check if a query uses an index and determine the query plan before execution. For more information, see . You can remove an index using the `DROP INDEX` statement in YCQL using the following syntax: ```sql DROP INDEX index_name; ``` For more information, see . {{% explore-setup-single %}} Suppose you work with a database that includes the following table populated with data: ```cql CREATE TABLE employees ( employee_no integer PRIMARY KEY, name text, department text ) WITH TRANSACTIONS = {'enabled':'true'}; ``` ```cql INSERT INTO employees(employee_no, name,department) VALUES(1221, 'John Smith', 'Marketing'); INSERT INTO employees(employee_no, name,department) VALUES(1222, 'Bette Davis', 'Sales'); INSERT INTO employees(employee_no, name,department) VALUES(1223, 'Lucille Ball', 'Operations'); ``` The following example shows a query that finds employees working in Operations: ```cql SELECT * FROM employees WHERE department = 'Operations'; ``` To process the preceding query, the whole `employees` table needs to be scanned and all the shards have to be accessed. For large organizations, this will take a significant amount of time. You can confirm this using the following `EXPLAIN` statement which indicates `seq scan` on the table. ```cql EXPLAIN SELECT * FROM employees WHERE department = 'Operations'; ``` ```output QUERY PLAN Seq Scan on employees Filter: (department = 'Operations') ``` To speed up the process, you create an index for the department column, as follows: ```cql CREATE INDEX indexemployeesdepartment ON employees(department); ``` The following example executes the query after the index has been applied to `department` and uses the `EXPLAIN` statement to prove that the index is used during query execution: ```cql EXPLAIN SELECT * FROM employees WHERE department = 'Operations'; ``` Following is the output produced by the preceding example: ```output QUERY PLAN -- Index Scan using docs.indexemployeesdepartment on docs.employees Key Conditions: (department = 'Operations') ``` To remove the index `indexemployeesdepartment`, use the following command: ```cql DROP INDEX indexemployeesdepartment; ``` Multi-column indexes can be beneficial in situations where queries are searching in more than a single

To add a multi-column index to an existing table, you can use the following syntax: ```sql CREATE INDEX indexname ON tablename(col2,col3,col4); ``` The column order is very important when you create a multi-column index in YCQL because of the structure in which the index is stored. As such, these indexes have a hierarchical order from left to right. So, for the preceding syntax, you can perform search using the following column combinations: ```sql (col2) (col2,col3) (col2,col3,col4) ``` A column combination like (col2,col4) cannot be used to search or query a table. {{% explore-setup-single %}} Create a keyspace and a table as follows: ```cql ycqlsh> CREATE KEYSPACE example; ycqlsh> USE example; ycqlsh:example> CREATE TABLE employees ( employee_id int PRIMARY KEY, first_name text, last_name text, dept_name text) WITH TRANSACTIONS = {'enabled': 'true'}; ``` Insert data to the employees table as follows: ```cql ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(1223, 'Lucille', ' Ball', 'Operations'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(1433, 'Brett', ' Davis', 'Marketing'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(1439, 'Simon', ' Thompson', 'HR'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(7898, 'Jackson', ' Lee', 'Sales'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(7866, 'Dan', ' Shen', 'Marketing'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(5666, 'Rob', ' Mencey', 'Marketing'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(4321, 'Dave', ' Spencer', 'Operations'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(3214, 'Dave', ' Marley', 'Operations'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(4121, 'Leo', ' Marvin', 'Sales'); ycqlsh:example> INSERT INTO employees(employeeid, firstname, lastname, deptname) VALUES(4021, 'Jackson', ' Bob', 'Marketing'); ``` View the contents of the `employees` table: ```cql ycqlsh:example> select * from employees limit 2; ``` ```output employeeid | firstname | lastname | deptname -++--+ 3214 | Dave | Marley | Operations 1223 | Lucille | Ball | Operations ``` Suppose you want to query the subset of employees by their first and last names. The query plan using the `EXPLAIN` statement would look like the following: ```cql ycqlsh:example> EXPLAIN SELECT * FROM employees WHERE firstname='Dave' AND lastname='Marley'; ``` ```output QUERY PLAN Seq Scan on example.employees Filter: (firstname = 'Dave') AND (lastname = 'Marley') ``` To process the preceding query, the whole `employees` table needs to be scanned and all the shards have to be accessed. For large organizations, this will take a significant amount of time as the query is executed sequentially as demonstrated in the preceding EXPLAIN statement. To speed up the process, you can create an index for `firstname` and `lastname` columns, as follows: ```cql ycqlsh:example> Create INDEX indexname ON employees2(firstname, last_name); ``` The following example executes the query after the index has been applied to the columns `firstname` and `lastname` and uses the EXPLAIN statement to prove that the index participated in the processing of the query: ```cql EXPLAIN SELECT * FROM employees WHERE firstname='Dave' AND lastname='Marley'; ``` ```output QUERY PLAN -- Index Scan using example.index_name on example.employees2 Key Conditions: (first_name = 'Dave') Filter: (last_name = 'Marley') ```