MySQL ignore index

Рубрика: Development, MySQL | 21 July 2006, 15:47 | Vadim Voituk

Есть в MySQL такая, на мой взгляд достаточно важная, и тем не менее оставленная без внимания, функция как игнорирование индексов при SELECT-запросах.
Выглядит это достаточно просто:

SELECT
...
FROM table_name IGNORE INDEX (index_name1, index_name2)
WHERE
...

Документация описывает как эта функциональность работает при запросах с JOIN, но только вскольз касается остальных случаев.

Рассмотрим такой пример:

Предположим есть у нас такая таблица с двумя индексами (i_domain и i_c_time):

> show create table apache_traffic_logs_current\G
************* 1. row ***********
Table: apache_traffic_logs_current
Create Table: CREATE TABLE `apache_traffic_logs_current` (
`id` int(11) NOT NULL auto_increment,
`nds` smallint(6) NOT NULL default '0',
`domain` char(100) NOT NULL default '',
`c_time` datetime NOT NULL default '0000-00-00 00:00:00',
`log_timestamp` int(5) NOT NULL default '0',
`abonentN` bigint(20) NOT NULL default '0',
`url` char(255) NOT NULL default '',
`method` char(10) NOT NULL default '',
`user_agent` char(255) NOT NULL default '',
`bytes` int(11) NOT NULL default '0',
`client_ip` char(15) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `c_time` (`c_time`),
KEY `i_domain` (`domain`)
) ENGINE=MyISAM
1 row in set (1.15 sec)

Выполним такие 2 запроса:

> explain select count(*) from apache_umc_traffic_logs_current WHERE c_time>='2006-06-01 00:00:00'\G
************* 1. row ***********
id: 1
select_type: SIMPLE
table: apache_umc_traffic_logs_current
type: range
possible_keys: i_c_time
key: i_c_time

key_len: 8
ref: NULL
rows: 17611471
Extra: Using where; Using index
1 row in set (0.02 sec)

> select count(*) from apache_traffic_logs_current WHERE c_time>=’2006-06-01 00:00:00′;
+———-+
| count(*) |
+———-+
| 41990638 |
+———-+
1 row in set (6 min 17.66 sec)

Глядя на EXPLAIN видим что индекс i_domain не используется в запросе.

Насильно пробуем указать оптимизатору SQL-запросов что этот индекс не нужен:

> select count(*) from apache_traffic_logs_current IGNORE INDEX (i_domain) WHERE c_time>='2006-06-01 00:00:00';
+----------+
| count(*) |
+----------+
| 41990638 |
+----------+
1 row in set (12 min 42.68 sec)

Сравниваем разницу времени выполнения первого и второго SELECT-запроса и жутко удивляемся – не много не мало в 2 раза, причем не в пользу насильного указания “не использовать индекс”.

Причину такого поведения я так и не нашел, но впредь использовать конструкцию IGNORE INDEX буду ОЧЕНЬ осторожно.

Комментариев: 2

2 Responses to “MySQL ignore index”

Комментарии:

  1. Radik

    При сложных сортировках и выборках прирост в 10-ки раз, тестировал на базе в 100000 записей (более 200 мб).

  2. vadim

    А можно начальные условия теста в студию?

Leave a Reply