Before you begin
Start the on a CockroachDB demo cluster with a larger data set.movr database preloaded and set as the .
Issue: Full table scans
The most common reason for slow queries is sub-optimalSELECT statements that include full table scans and incorrect use of indexes.
You’ll get generally poor performance when retrieving a small number of rows from a large table based on a column that is not in the primary key or any secondary index:
table: users@users_pkey indicates the index used (users_pkey) to scan the table (users). spans: FULL SCAN shows you that, without a secondary index on the name column, CockroachDB scans every row of the users table, ordered by the primary key (city/id), until it finds the row with the correct name value.
Solution: Filter by a secondary index
To speed up this query, add a secondary index onname:
users@users_name_idx). Because it is sorted by name, the query can jump directly to the relevant value (/'Cheyenne Smith' - /'Cheyenne Smith'). However, the query needs to return values not in the secondary index, so CockroachDB grabs the primary key (city/id) stored with the name value (the primary key is always stored with entries in a secondary index), jumps to that value in the primary index, and then returns the full row.
Because the users table is under , the primary index and all secondary indexes are contained in a single range with a single leaseholder. If the table were bigger, however, the primary index and secondary index could reside in separate ranges, each with its own leaseholder. In this case, if the leaseholders were on different nodes, the query would require more network hops, further increasing latency.
Solution: Filter by a secondary index storing additional columns
When you have a query that filters by a specific column but retrieves a subset of the table’s total columns, you can improve performance by those additional columns in the secondary index to prevent the query from needing to scan the primary index as well. For example, let’s say you frequently retrieve a user’s name and credit card number:name, CockroachDB still needs to scan the primary index to get the credit card number:
name, this time storing the credit_card value in the index:
credit_card values are stored in the index on name, CockroachDB only needs to scan that index:
name:
Issue: Joining data from different tables
Secondary indexes are crucial when data from different tables as well. For example, let’s say you want to count the number of users who started rides on a given day. To do this, you need to use a join to get the relevant rides from therides table and then map the rider_id for each of those rides to the corresponding id in the users table, counting each mapping only once:
rides to get all rows with a start_time in the specified range and then does another full table scan on users to find matching rows and calculate the count.
Given the WHERE condition of the join, the full table scan of rides is particularly wasteful.
Solution: Create a secondary index on the WHERE condition storing the join key
To speed up the query, you can create a secondary index on the WHERE condition (rides.start_time) storing the join key (rides.rider_id):
rides@rides_start_time_idx secondary index to retrieve the relevant rides without needing to scan the full rides table.
Issue: Inefficient joins
are more expensive and require more memory than . Hence the uses a lookup join whenever possible. For the following query, the cost-based optimizer can’t perform a lookup join because the query doesn’t have a prefix of therides table’s primary key available and thus has to read the entire table and search for a match, resulting in a slow query:

