Почему MySQL не использует какой-либо из этих возможных ключей?

У меня есть следующий запрос:

SELECT t.id
FROM account_transaction t
JOIN transaction_code tc ON t.transaction_code_id = tc.id
JOIN account a ON t.account_number = a.account_number
GROUP BY tc.id

Когда я делаю EXPLAIN, первая строка показывает, среди прочего, следующее:

table: t
type: ALL
possible_keys: account_id,transaction_code_id,account_transaction_transaction_code_id,account_transaction_account_number
key: NULL
rows: 465663

Почему ключ NULL?

Ответ 1

Возможно, это связано с тем, что статистика разбита или потому, что она знает, что у вас всегда есть соотношение 1:1 между двумя таблицами.

Вы можете заставить индекс использоваться в запросе и посмотреть, ускорит ли это действие. Если это так, попробуйте запустить ANALYZE TABLE, чтобы убедиться, что статистика обновлена.

Указывая USE INDEX (index_list), вы можете указать MySQL использовать только один из названных индексов для поиска строк в таблице. Альтернативный синтаксис IGNORE INDEX (index_list) можно использовать, чтобы сообщить MySQL не использовать какой-либо определенный индекс или индексы. Эти подсказки полезны, если EXPLAIN показывает, что MySQL использует неверный индекс из списка возможных индексов.

Вы также можете использовать FORCE INDEX, который действует как USE INDEX (index_list), но с добавлением, что сканирование таблицы считается очень дорогостоящим. Другими словами, сканирование таблицы используется только в том случае, если нет способа использовать один из указанных индексов для поиска строк в таблице.

В каждом подсказке требуются имена индексов, а не имена столбцов. Имя ПЕРВИЧНОГО КЛЮЧА ПЕРВИЧНО. Чтобы увидеть имена индексов для таблицы, используйте SHOW INDEX.

Из http://dev.mysql.com/doc/refman/5.1/en/index-hints.html

Ответ 2

Другой проблемой, с которой вы можете столкнуться, является неправильное совпадение типов данных. Например, если ваш столбец является строковым типом данных (CHAR, для ex), и ваш запрос не цитирует число, тогда MySQL не будет использовать индекс.

SELECT * FROM tbl WHERE col = 12345; # No index
SELECT * FROM tbl WHERE col = '12345'; # Index

Источник: только что вошел в эту же проблему сегодня и усердно изучил MySQL 5.1.:)

Изменить: дополнительную информацию для подтверждения:

mysql> desc das_table \G
*************************** 1. row ***************************
  Field: das_column
   Type: varchar(32)
   Null: NO
    Key: PRI
Default: 
  Extra: 
*************************** 2. row ***************************
[SNIP!]

mysql> explain select * from das_table where das_column = 189017 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: das_column
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 874282
        Extra: Using where
1 row in set (0.00 sec)

mysql> explain select * from das_table where das_column = '189017' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: das_column
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 34
          ref: const
         rows: 1
        Extra: 
1 row in set (0.00 sec)

Ответ 3

Указатель для group by (= неявный order by)

...
GROUP BY tc.id

Группа с помощью неявного сортировки на tc.id.
tc.id не указан в качестве возможного ключа.
но t.transaction_id -.

Измените код на

SELECT t.id
FROM account_transaction t
JOIN transaction_code tc ON t.transaction_code_id = tc.id
JOIN account a ON t.account_number = a.account_number
GROUP BY t.transaction_code_id

Это приведет к представлению потенциального индекса transaction_code_id.

Индексы для объединений
Если соединения (почти) полностью присоединяются к трем таблицам, нет необходимости использовать индекс, поэтому MySQL этого не делает.

Другие причины не использовать индекс
Если большая часть рассматриваемых строк (40% IIRC) заполняется с одинаковым значением. MySQL не использует индекс. (потому что не использовать индекс быстрее)