Как расширение индекса в InnoDB таблицах удивительным образом снижает производительность

Автор оригинала: Пётр Зайцев
  • Перевод
Один из видов оптимизации, который мы часто используем, это расширение индекса. Он подходит, если есть запросы, использующие другие части составного ключа. И обычно это безопасно, но есть некоторые случаи, где производительность катастрофически падает.

Рассмотрим пример.

У нас есть таблица

CREATE TABLE `idxitest` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=6029313 DEFAULT CHARSET=latin1

mysql> SELECT count(*) FROM idxitest WHERE a=5 AND b=5;
+----------+
| count(*) |
+----------+
|    60434 |
+----------+
1 row IN SET (0.69 sec)
 
mysql> EXPLAIN SELECT count(*) FROM idxitest WHERE a=5 AND b=5;
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
| id | select_type | TABLE    | type | possible_keys | KEY  | key_len | ref   | rows   | Extra       |
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
|  1 | SIMPLE      | idxitest | ref  | a             | a    | 4       | const | 707820 | USING WHERE |
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
1 row IN SET (0.00 sec)


Самое очевидное решение — это расширить вправо ключ с колонки «a» на две колонки (a, b). Вроде бы это не должно никак отрицательно повлиять на другие запросы.

mysql> ALTER TABLE idxitest DROP KEY a,ADD KEY(a,b);
Query OK, 0 rows affected (24.84 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT count(*) FROM idxitest WHERE a=5 AND b=5;
+----------+
 | count(*) |
+----------+
 |    60434 |
+----------+
1 row IN SET (0.02 sec)
       
mysql> EXPLAIN SELECT count(*) FROM idxitest WHERE a=5 AND b=5;
+----+-------------+----------+------+---------------+------+---------+-------------+--------+-------------+
 | id | select_type | TABLE    | type | possible_keys | KEY  | key_len | ref         | rows   | Extra       |
+----+-------------+----------+------+---------------+------+---------+-------------+--------+-------------+
 |  1 | SIMPLE      | idxitest | ref  | a             | a    | 8       | const,const | 120640 | USING INDEX |
+----+-------------+----------+------+---------------+------+---------+-------------+--------+-------------+
1 row IN SET (0.00 sec)


Круто. Запрос стал быстрее в 30 раз. Во-первых, он сканирует меньше строк, а во-вторый, использует покрывающий индекс, то есть все нужные данные извлекает прямо из индекса.

Однако рано радоваться. В приложении есть ещё один запрос, который до этого был настолько быстр, что его трудно было заметить. Теперь он стал намного медленее.

Было
mysql> SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+---------+-----+---+
| id	  | a   | b 
+---------+-----+---+
| 3000000 | 100 | 7 
+---------+-----+---+
1 row IN SET (0.00 sec)
mysql> EXPLAIN SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
| id | select_type | TABLE	| type | possible_keys | KEY  | key_len | ref   | rows   | Extra	   
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
|  1 | SIMPLE	  | idxitest | ref  | a			 | a	| 4	   | const | 126074 | USING WHERE 
+----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
1 row IN SET (0.00 sec)


Стало
mysql> SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+---------+-----+---+
| id	  | a   | b 
+---------+-----+---+
| 3000000 | 100 | 7 
+---------+-----+---+
1 row IN SET (1.01 sec)
mysql> EXPLAIN SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | TABLE	| type  | possible_keys | KEY	 | key_len | ref  | rows | Extra	   
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE	  | idxitest | INDEX | a			 | PRIMARY | 4	   | NULL |   36 | USING WHERE 
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
1 row IN SET (0.00 sec)
# The plan also can look something like this:
mysql> EXPLAIN SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+----+-------------+----------+------+---------------+------+---------+-------+------+------------------------------------------+
| id | select_type | TABLE	| type | possible_keys | KEY  | key_len | ref   | rows | Extra
+----+-------------+----------+------+---------------+------+---------+-------+------+------------------------------------------+
|  1 | SIMPLE	  | idxitest | ref  | a			 | a	| 4	   | const |	1 | USING WHERE; USING INDEX; USING filesort 
+----+-------------+----------+------+---------------+------+---------+-------+------+------------------------------------------+
1 row IN SET (0.01 sec)


Почему этот запрос стал медленее? Причина в том, что его план выполнения выигрывал от одной особенности InnoDB — все индексные записи всегда отсортированы по первичному ключу. То есть когда у вас есть индекс (a) и первичный ключ id, то реальный ключ у вас (a, id). Когда же мы расширяем ключ до (a, b), то фактически получаем (a, b, id). Наш запрос использовал обе части исходного ключа «a» и «id» (для сортировки). Теперь же он не сможет полностью использовать новый индекс.

Какое решение проблемы? Придётся создать избыточный индекс и держать одновременно (a) и (a, b). Обычно это должно сработать, хотя не всегда.

CREATE TABLE `idxitest` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `a_2` (`a`,`b`)
) ENGINE=InnoDB AUTO_INCREMENT=6029313 DEFAULT CHARSET=latin1
mysql> SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+---------+-----+---+
| id	  | a   | b 
+---------+-----+---+
| 3000000 | 100 | 7 
+---------+-----+---+
1 row IN SET (1.03 sec)
mysql> EXPLAIN SELECT * FROM  idxitest  WHERE a=100 ORDER BY id DESC LIMIT 1;
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | TABLE	| type  | possible_keys | KEY	 | key_len | ref  | rows | Extra	   
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE	  | idxitest | INDEX | a,a_2		 | PRIMARY | 4	   | NULL | 2247 | USING WHERE 
+----+-------------+----------+-------+---------------+---------+---------+------+------+-------------+
1 row IN SET (0.00 sec)


Оптимизатор запросов рассматривает возможность использования обоих индексов и в конце концов отвергает оба, делая полное сканирование индекса до того, как найдёт a=100. Это выглядит так, будто оптимизатор глючит. Он собирается просканировать 2247 строк, тогда как достаточно одной строки, используя индекс (a).

Поэтому вам придётся заставить оптимизатор выбрать правильный план выполнения запроса, добавив FORCE INDEX(a).

Как показал данный пример, надо быть очень аккуратным, играясь с индексами. Если у вас есть запросы, план выполнения которых выигрывает от сортировки InnoDB по первичному ключу, то они могут быть значительно затронуты.

По-разному может вести себя оптимизатор в разных версиях MySQL. Мы проверили в версии 5.1.45, хотя такое же поведение было обнаружено и в 5.0.

Средняя зарплата в IT

120 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 3 429 анкет, за 1-ое пол. 2021 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

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

    +11
    Как расширение индекса удивительным образом снижает производительность
    Верните пожалуйста в заголовок упоминание InnoDB, как в оригинале у Зайцева. Увидев такое падение производительности я не поверил своим глазам поначалу, пока в тексте не увидел упоминание innodb. К myisam, например, этот топик никакого отношения не имеет, ну кроме, пожалуй, совета осторожно играть с индексами, это всегда надо делать с умом.
      0
      Спасибо, исправил.
      –14
      Я с 3-го раза только прочел «расширение индекса», т.к. читалось «расширение яндекса» :) Подумалось, что яндекс пишет к mysql плагины :) П.С. Спасибо за статью.
        +3
        Для запроса типа
        EXPLAIN SELECT * FROM idxitest WHERE a=100 ORDER BY id DESC LIMIT 1;
        желательно создавать индекс на полях (a, id) для его автоматического использования. Это поведение подробно описано в dev.mysql.com/doc/refman/5.1/en/order-by-optimization.html.
          0
          точка в конце линка лишняя получилась.
            +1
            Смысл статьи в том, чтобы сделать акцент для тех кто не знает — что id (PK) уже есть как значение индекса

            >> То есть когда у вас есть индекс (a) и первичный ключ id, то реальный ключ у вас (a, id).
              +1
              Читать, соответственно тут: dev.mysql.com/doc/refman/5.1/en/innodb-index-types.html
                0
                «оптимизатор запросов рассматривает возможность использования обоих индексов и в конце концов отвергает оба»
                а как понимать причину отказа от двух индексов?
                  0
                  > Это выглядит так, будто оптимизатор глючит.
                  :)
                    0
                    а, ну это тогда всё объясняет :)
                    +2
                    я не знаю, почему Пётр так написал, но на плане запроса вполне видно, что оптимизатор не отказался от индексов совсем. KEY == PRIMARY. т.е. оптимизатор решил выбрать отсортированную коллекцию и решил пройтись по ней, ища нужное a = 100. почему он так выбрал? потому что вес у данного варианта больше, чем у другого.

                    особо я не понимаю Петра в этой вот части: «This looks like an optimizer glitch in this case because it estimates it will scan 2247 rows in the selected plan, while using (a) index you can get result scanning only 1 row guaranteed.»
                    индекс по «a» НЕУНИКАЛЬНЫЙ. откуда там взяться 1 row guaranteed — непонятно. чтобы выполнить эту операцию — нужно выбрать все записи с a=100, отсортировать их (а их может быть и 10М), и выбрать первую, с минимальным id.
                0
                Одному мне кажется очевидным, что если я создаю индекс для пары значений, то для одного значения этот индекс и не будет использоваться?
                  +2
                  это неочевидно. более того — ваше утверждение в корне неверно.
                  если создан индекс a+b, то он **БУДЕТ** использоваться для a
                    –2
                    С какого перепуга он будет использоваться? Индекс строится для пары a и b в случае если ищем только одну из частей этот индекс не будет использоваться, потому что он строится именно для пары значений. В топике explain четко указывает это.
                      +1
                      я советую вам почитать матчасть о индексах. хотя если вы будете настаивать и продолжать выставлять себя невеждой и человеком, не способным в документации (или гугле) почитать, как работают составные индексы — я дам вам прямую ссылку на описание на dev.mysql.com
                        0
                        «Почему этот запрос стал медленее? Причина в том, что его план выполнения выигрывал от одной особенности InnoDB — все индексные записи всегда отсортированы по первичному ключу. То есть когда у вас есть индекс (a) и первичный ключ id, то реальный ключ у вас (a, id). Когда же мы расширяем ключ до (a, b), то фактически получаем (a, b, id). Наш запрос использовал обе части исходного ключа «a» и «id» (для сортировки). Теперь же он не сможет полностью использовать новый индекс.»

                        думаю, проблема как раз в «ORDER BY id», а не в матчасти :)

                          0
                          как это оправдывает незнание человеком работы leftmost части индексов?
                            0
                            прошу прощения, похоже я не в тему :)
                          –1
                          mysql> EXPLAIN SELECT * FROM idxitest WHERE a=100 ORDER BY id DESC LIMIT 1;
                          +----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
                          | id | select_type | TABLE | type | possible_keys | KEY | key_len | ref | rows | Extra
                          +----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
                          | 1 | SIMPLE | idxitest | ref | a | a | 4 | const | 126074 | USING WHERE
                          +----+-------------+----------+------+---------------+------+---------+-------+--------+-------------+
                          1 row IN SET (0.00 sec)

                          Где тут используется индекс (a,b)? Если у вас есть ссылка я с удовольствием почитаю, как он их использует.
                            0
                            1. как это связано с исходным твоим комментом?

                            2. по обсуждаемому вопросу «Индекс строится для пары a и b в случае если ищем только одну из частей этот индекс не будет использоваться, потому что он строится именно для пары значений.»

                            mysql> EXPLAIN SELECT indexx from doma where indexx = '453252'  AND gninmb = '0266';
                            +----+-------------+-------+------+---------------+---------------+---------+-------------+------+--------------------------+
                            | id | select_type | table | type | possible_keys | key           | key_len | ref         | rows | Extra                    |
                            +----+-------------+-------+------+---------------+---------------+---------+-------------+------+--------------------------+
                            |  1 | SIMPLE      | doma  | ref  | indexx_gninmb | indexx_gninmb | 32      | const,const |   20 | Using where; Using index |
                            +----+-------------+-------+------+---------------+---------------+---------+-------------+------+--------------------------+
                            1 row in set (0.00 sec)
                            
                            mysql> EXPLAIN SELECT indexx from doma where indexx = '453252';
                            +----+-------------+-------+------+---------------+---------------+---------+-------+------+--------------------------+
                            | id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra                    |
                            +----+-------------+-------+------+---------------+---------------+---------+-------+------+--------------------------+
                            |  1 | SIMPLE      | doma  | ref  | indexx_gninmb | indexx_gninmb | 19      | const |   20 | Using where; Using index |
                            +----+-------------+-------+------+---------------+---------------+---------+-------+------+--------------------------+
                            1 row in set (0.00 sec)
                            


                            особо обращаю внимание на поля key и key_len.
                              0
                              как это связано с исходным твоим комментом

                              Выше смотрим:
                              В топике explain четко указывает это.

                                0
                                Не указывает. EXPLAIN (и комментарии Петра) указывают лишь на то, что оптимизатор mysql колбасит и он выбирает неоптимальные решения. По всем правилам индекс использоваться должен, индекс a+id. То, что он не используется — ошибка анализатора, как следствие — баг субд.
                              0
                              ну и вот на сладенькое: dev.mysql.com/doc/refman/5.1/en/mysql-indexes.html со слов «If the table has a multiple-column index, any leftmost» + dev.mysql.com/doc/refman/5.1/en/order-by-optimization.html второй пример в первой группе примеров
                                0
                                Про leftmost не знал и видимо у меня обычно индекс строился так что multiplie-column index не использовался. Буду знать и пользовать :]
                            0
                            Если индекс составной (a, b), то операция сравнения идёт слева направо. ТОгда индекс будет справделив для вариантов
                            WHERE a =?
                            WHERE a =? AND b =?
                            Но индекс не будет использоваться в случае
                            WHERE b =?
                              0
                              вы, наверное, еще и думаете, что индекс (a,b) это тоже самое что и (b,a)?
                        +1
                        А почему бы не создать два отдельных индекса на (a) и (b) вместо (a), (a, b)?
                          0
                          потому что всегда используется только один индекс
                            0
                            Провел эксперимент:

                            индекс на полях currency_id и transaction_type

                            [accounting_user]>select count(id) from ledger where currency_id = 1 and transaction_type = 'invoice';
                            +-----------+
                            | count(id) |
                            +-----------+
                            | 13197 |
                            +-----------+
                            1 row in set (0.04 sec)

                            [accounting_user]>explain select count(id) from ledger where currency_id = 1 and transaction_type = 'invoice';
                            +----+-------------+--------+-------------+------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
                            +----+-------------+--------+-------------+------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            | 1 | SIMPLE | ledger | index_merge | currency_id,transaction_type | transaction_type,currency_id | 1,4 | NULL | 3749 | Using intersect(transaction_type,currency_id); Using where; Using index |
                            +----+-------------+--------+-------------+------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            1 row in set (0.05 sec)



                            добавляем индекс на (currency_id, transaction_type)
                            запрос отрабатывает те же 0.04 сек

                            [accounting_user]>explain select count(id) from ledger where currency_id = 1 and transaction_type = 'invoice';
                            +----+-------------+--------+-------------+-------------------------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
                            +----+-------------+--------+-------------+-------------------------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            | 1 | SIMPLE | ledger | index_merge | currency_id,transaction_type,transaction_type_2 | transaction_type,currency_id | 1,4 | NULL | 3764 | Using intersect(transaction_type,currency_id); Using where; Using index |
                            +----+-------------+--------+-------------+-------------------------------------------------+------------------------------+---------+------+------+-------------------------------------------------------------------------+
                            1 row in set (0.00 sec)


                              0
                              а что, если над таблицей сделать OPTIMIZE + ANALYZE?

                              плюс всё таки схему хотелось бы увидеть.
                                0
                                ха, а я и не знал что в 5ой версии есть объединение индексов
                                мой коммент следовательно ошибка
                                  0
                                  Наконец то! :) я тут ОЧЕНЬ сильно удивился, что нужно подобные индексы делать. Провел тесты — отдельные индексы на каждое поле работают замечательно!

                                  В примере в статье автор создал составной индекс и дропнул одиночный. А потому удивляется, куда же делась производительность.
                                    +1
                                    для сортировки мердж использован не будет. поэтому в статье автор ничего неправильного не сделал.
                                      0
                                      Ну видимо не всегда они работают замечательно.

                                      +----+------+-------+
                                      | id | name | level |
                                      +----+------+-------+
                                      | 1 | 1 | 1 |
                                      | 2 | 2 | 1 |
                                      | 3 | 2 | 2 |
                                      | 4 | 2 | 2 |
                                      | 5 | 1 | 3 |
                                      +----+------+-------+

                                      На такой табличке заставить мускуль использовать index merge не получилось. Составной использовался, одиночный использовался (какой поменьше).

                                      Server version: 5.1.45 Source distribution
                                    0
                                    у вас currency_id — уникальное поле?
                                      0
                                      нет
                                  0
                                  Потому что это два раздельных индекса на значения a и значение b. Эти два индекса использовать для поиска пары значений не эффективно.
                                    0
                                    А если у меня 5 полей в таблице и есть необходимость искать строки по совпадениям различных пары, троек значений — это мне нужно создавать все возможные пересечения индексов? например (a,b), (a,c), (c,d), (a,c,d) — как то это очень странно. В моем примере видно, что на скорость выполнения запроса не влияет и замечательно используется index_merge
                                      0
                                      в очередной раз — ваша фраза абсолютно некорректна в той её части, что два индекса использовать для поиска пары не то что неэффективно, а НЕВОЗМОЖНО в принципе
                                          0
                                          да знаю я про мердж. другое дело — что его поведние не совсем управляется и на него расчитывать не нужно. я отвечал человеку, который не понимает принципиально, как работают индексы и не надеялся, что кто-то из _понимающих_ поправит меня :-)
                                            0
                                            охохохо, меня поправил человек, родившийся в один день со мной. вот это неожиданность )))
                                              +1
                                              хехе, тыдыщь! )))
                                            0
                                            Можно сделать вложенные запросы через join, но вообще для поиска пары в прямом поиске использоваться не будут.
                                        0
                                        Где-то выигрываем, где-то проигрываем, в идеале надо затачивать каждый запрос и не обращать внимание на кол-во индексов, хотя тут уже появятся другие грабли.
                                          0
                                          Какое решение проблемы? Придётся создать избыточный индекс и держать одновременно (a) и (a, b)

                                          А чем не устраивает (a) и (b)? — В отличие от вашего варианта мы получим еще и оптимизацию при поиске по ключу b и экономию места на ключах (последнее конечно спорно). И версия у вас 5.1.45 и статья в плюсах… Кучу народа в заблуждение введет! Хабр уже не торт (
                                            0
                                            index merge очень непредсказуем, более того — он работает не во всех вариантах, где работает (a,b)
                                              0
                                              Возможно, но как минимум об этом нужно написать в статье.
                                                0
                                                не нужно :-) статья не об этом была. статья была о том, что люди часто забывают, что в secondary index'ах PK добавляется последним полем.
                                                и рассмотрен пример, где это видно очевидно — фильтрация по a и сортировка по PK
                                                и как раз в этой ситуации index merge работать не будет
                                                  0
                                                  Приведите пожалуйста пример, когда нужен именно составной индекс.
                                                    0
                                                    WHERE `a` = const ORDER BY `b`

                                                    как самый простой пример

                                                    плюс в запросах, когда index range, составной индекс ВСЕГДА будет быстрее index merge
                                                      +1
                                                      Давайте возьмем случай посложнее. В таблице примерно 30 млн строк
                                                      CREATE TABLE `ix` (
                                                       `a` int(11) unsigned NOT NULL,
                                                       `b` int(11) unsigned NOT NULL,
                                                       KEY `a` (`a`),
                                                       KEY `b` (`b`)
                                                      ) ENGINE=MyISAM

                                                      mysql> explain SELECT COUNT(*) FROM ix WHERE a BETWEEN 50000 AND 60000
                                                      AND b BETWEEN 50000 AND 60000 \G
                                                      *************************** 1. row ***************************
                                                                id: 1
                                                       select_type: SIMPLE
                                                              table: ix
                                                               type: range
                                                      possible_keys: a,b
                                                               key: a
                                                           key_len: 4
                                                               ref: NULL
                                                               rows: 165334
                                                              Extra: Using where
                                                      1 row in set (0.00 sec)

                                                      mysql> SELECT COUNT(*) FROM ix WHERE a BETWEEN 50000 AND 60000
                                                      AND b BETWEEN 50000 AND 60000 \G
                                                      *************************** 1. row ***************************
                                                      count(*): 2624
                                                      1 row in set (0.75 sec)

                                                      Как видите mysql уже не может использовать merge. Добавляем составной индекс ab (a,b )
                                                      mysql> explain SELECT COUNT(*) FROM ix WHERE a BETWEEN 50000 AND 60000
                                                      AND b BETWEEN 50000 AND 60000 \G
                                                      *************************** 1. row ***************************
                                                                id: 1
                                                       select_type: SIMPLE
                                                              table: ix
                                                               type: range
                                                      possible_keys: a,b,ab
                                                               key: ab
                                                           key_len: 8
                                                               ref: NULL
                                                               rows: 231045
                                                              Extra: Using where; Using index
                                                      1 row in set (0.00 sec)

                                                      mysql> SELECT COUNT(*) FROM ix WHERE a BETWEEN 50000 AND 60000
                                                      AND b BETWEEN 50000 AND 60000 \G
                                                      *************************** 1. row ***************************
                                                      count(*): 2624
                                                      1 row in set (0.16 sec)
                                                      В целом всё зависит от данных, если таблицы небольшие и запросы просты — то и merge прокатит. Если я на этой таблице повторю исходный запрос (т.е. a=const and b=const) то быстрее все равно будет запрос с составным индексом, но разница будет незначительная. Оно и понятно — объединение индексов сама по себе операция и время какое то занимает.

                                                      До кучи к вышесказанному примеру с сортировкой еще не забывайтся, что запрос вида
                                                      SELECT a,b FROM ix WHERE ...
                                                      в случае составного индекса результат будет отдавать непосредственно из индекса, даже не обращаясь непосредственно к данным. В случае с merge этого не будет, впрочем тут я не уверен, возможно в более новых версиях mysql этому научили.
                                                        0
                                                        Да-да, спасибо. dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html здесь тоже неплохо описано.
                                                          0
                                                          эмм… причем здесь оптимизация order by?
                                                            0
                                                            Здесь написано, в каких случаях не будут использоваться индексы при сортировках.
                                                              0
                                                              я разве что то писал про сортировки?
                                                                0
                                                                Вы — нет. Комментатор выше вас писал. А Ваш пример с between очень хороший.
                                                          0
                                                          эм, очень занятно. а как он может использовать b из индкса a+b? у нас ведь index range по a.
                                                0
                                                Ошибся, ответ не вам — хотел в основную ветку написать.
                                                0
                                                У меня и в MyISAM бывал тупняк с неправильным выбором индекса в запросе. Причем на локальной машинке 5.1 стоит и всё хорошо, а на хостинге с 5.0 внезапно начинается какой-то ужас.
                                                Просто заюзал FORCE INDEX.

                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                Самое читаемое