2013-10-02 3 views
3

У меня есть таблица тестов (таблица1) с 6 записями в ней. Я хотел получить данные на основе столбца (col1) для нескольких значений. Итак, я проиндексировал столбец. Теперь, если я передаю несколько значений в разделе IN, выбирая все столбцы (*) с принудительным индексом, я получаю конкретные записи вместо полного сканирования таблицы. Если я запускаю тот же запрос с выбранным столбцом, я вижу, что он выполняет полное сканирование таблицы.Mysql IN clause full table scan

Я прочитал, что использование select all (*) в запросе select не очень хорошо. Но здесь, если я не использую select all (*), будет развернуто полное сканирование таблицы. Я не могу понять, как mysql читает запрос. Пожалуйста, помогите мне разобраться с этой проблемой.

ТАБЛИЦА

+----+--------+---------+ 
| id | col1 | col2 | 
+----+--------+---------+ 
| 1 | 100000 | E100000 | 
| 2 | 100001 | E200001 | 
| 3 | 100002 | E300002 | 
| 4 | 100003 | E400003 | 
| 5 | 100004 | E500004 | 
| 6 | 100005 | E600005 | 
+----+--------+---------+ 

ИНДЕКС

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
| table1 |   0 | PRIMARY |   1 | id   | A   |   6 |  NULL | NULL |  | BTREE  |   |    | 
| table1 |   1 | col1  |   1 | col1  | A   |   6 |  NULL | NULL |  | BTREE  |   |    | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

EXPLAIN (использование силы INDEX (col1) и выбора всех (*) столбцы)

select * from table1 force index(col1) where col1 in ('100000', '100001'); 

+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+ 
| 1 | SIMPLE  | table1 | range | col1   | col1 | 10  | NULL | 2 | Using where | 
+----+-------------+----------+-------+---------------+-------+---------+------+------+-------------+ 

EXPLAIN (ИСПОЛЬЗОВАНИЕ СИЛЫ INDEX (col1) и выбор только 1 столбец данных вместо всех (*))

select col1 from table1 force index(col1) where col1 in ('100000', '100001'); 

+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra     | 
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+ 
| 1 | SIMPLE  | table1 | range | col1   | col1 | 10  | NULL | 6 | Using where; Using index | 
+----+-------------+----------+-------+---------------+-------+---------+------+------+--------------------------+ 
+0

на самом деле это сложнее, ваш стол очень маленький, поэтому полное сканирование является лучшим для него :) – Gar

+0

@Gar: вышеперечисленная таблица - это всего лишь тестовая таблица, в исходной таблице будет более 60 000 записей – sravis

+1

Если количество требуемых записей является довольно большим процентом от количества доступных записей, то MySQL не хочет беспокоиться об индексах. Добавьте еще несколько десятков тестовых записей, и я подозреваю, что результаты изменятся. – Kickstart

ответ

1
  1. MySQL оптимизатор видит, что таблица слишком мало, и полное сканирование будет более эффективным чем сначала поиск индекса, так и извлечение данных позже.
  2. Когда вы выбираете только один столбец, оптимизатор MySQL видит, что этот столбец находится в индексе, и нет необходимости извлекать данные из таблицы - достаточно прочитать индекс.

Как оптимизатор определяет, что более эффективно? Он пытается предсказать количество операций чтения-блока диска.

Как уже упоминалось ранее в комментариях, на большом столе EXPLAIN будет отличаться.