В показываемых вами запросах (вероятно) задействовано два дерева BT. Одно дерево BTree для данных, отсортированное по PRIMARY KEY
, которое, как я полагаю, равно id
. Другой для INDEX
на user_id
(опять же, я предполагаю). Когда InnoDB (который, как я полагаю, вы используете) создает «вторичный индекс», такой как INDEX(user_id)
, он молча прикрепляет PK таблицы. Таким образом, фактически он становится BTree
, содержащим два столбца: (user_id, id)
и отсортированный по этой паре.
Когда оптимизатор просматривает SELECT * FROM t WHERE user_id=?
, он исследует таблицу и обнаруживает, что "много" строк было user_id = 1
, и не во многих строках были другие значения, которые вы пробовали.
Оптимизатор имеет два (или более) способа оценки подобных запросов -
План A (используйте индекс ): Вот что он делает:
- Просмотрите BTree индекса, чтобы найти первое вхождение
user_id=2
. - Там он найдет
id
. - Используйте этот
id
, чтобы развернуть BTree данных и найти *
(как в SELECT *
). - Перейдите к следующей записи в индексном BTree. (На самом деле это довольно эффективно, так как это действительно «дерево B +»; см. Википедию.)
- Если найдено, l oop возвращается к шагу 2. Если не найден (больше нет записей индекса с
user_id=2
), выход.
План B (не используйте индекс - полезно для user_id=1
):
- Просто пройдитесь по данным BTree в любом порядок.
- Пропустить любую строку, в которой нет
user_id=1
.
Перепрыгивание назад и вперед между двумя BT-деревьями стоит чего-то. Оптимизатор решил, что в вашем случае =1
необходимо просмотреть более 20% таблицы, и решил, что план Б будет быстрее. То есть он намеренно игнорировал ИНДЕКС.
Есть много факторов, которые Оптимизатор не может или неправильно оценивает, но обычно выбор между этими двумя планами приводит к более быстрому исполнение. (Ваша таблица слишком мала, чтобы надежно измерить разницу.)
Другие «планы» - если индекс «покрывает», нет необходимости использовать данные BTree. Если существует ORDER BY
, который можно использовать, тогда Оптимизатор вероятно будет использовать план A, чтобы избежать «сортировки файлов». (См. EXPLAIN SELECT ...
) Et c.