I'm having some trouble adding a new index to my table and I'm wondering why MySQL isn't using the new index.
I noticed that it only happens when my SELECT statement requests other colums which aren't part of the index (e.g. SELECT * doesn't work while SELECT id, otherId does work).
Can someone explain to me why MySQL chooses to do a table scan instead of using the index?
Database schema
The table consists of multiple columns, namely id and otherId. id is my primary key while otherId should get indexed as well. otherId can be null and is unique.
model Entity {
id String @id @default(cuid())
otherId String? @unique
// Few more ...
}
Cardinality and selectivity
SELECT
COUNT(DISTINCT Entity.otherId) as cardinality,
COUNT(*) as totalRows,
COUNT(Entity.otherId) as nonNullRows,
COUNT(DISTINCT Entity.otherId) / COUNT(*) as selectivity
FROM
Entity
| cardinality | totalRows | nonNullRows | selectivity |
|---|---|---|---|
| 171 | 1187 | 171 | 0.1441 |
EXPLAIN SELECT *
This one doesn't use the index but I wish it would.
EXPLAIN SELECT * FROM Entity WHERE Entity.otherId = ?;
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | Entity | ALL | Entity_otherId_key | 1187 | 10 | Using where |
EXPLAIN SELECT id, otherId
This one does use the index.
EXPLAIN SELECT id, otherId FROM Entity WHERE Entity.otherId = ?;
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | Entity | index | Entity_otherId_key | Entity_otherId_key | 767 | 1187 | 10 | Using where; Using index |
SHOW INDEXES
SHOW INDEXES from Entity;
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Entity | 0 | PRIMARY | 1 | id | A | 1187 | BTREE | YES | ||||||
| Entity | 0 | Entity_otherId_key | 1 | otherId | A | 172 | YES | BTREE | YES |
MySQL version
8.2.0
SELECT VERSION();and report what it says?type: ALLin the second query? I would expect it to saytype: index, unless they've changed the implementation of EXPLAIN reports.