Одно из моих приложений делает изрядное количество:
select count(distinct id) from x;
с id
основным ключ для таблицы x
. В MySQL 5.1 (и 5.0) это выглядит так:
mysql> explain SELECT count(distinct id) from x;
+----+-------------+----------+-------+---------------+-----------------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+-----------------+---------+------+---------+-------------+
| 1 | SIMPLE | x | index | NULL | ix_blahblahblah | 1 | NULL | 1234567 | Using index |
+----+-------------+----------+-------+---------------+-----------------+---------+------+---------+-------------+
В InnoDB это не совсем так, но и неплохо.
На этой неделе я Я пробую MySQL 5.5.11 и с удивлением обнаружил, что тот же запрос выполняется во много раз медленнее. С заполненным кешем это занимает около 90 секунд по сравнению с 5 секундами ранее. Теперь план выглядит следующим образом:
mysql> explain select count(distinct id) from x;
+----+-------------+----------+-------+---------------+---------+---------+------+---------+-------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+------+---------+-------------------------------------+
| 1 | SIMPLE | x | range | NULL | PRIMARY | 4 | NULL | 1234567 | Using index for group-by (scanning) |
+----+-------------+----------+-------+---------------+---------+---------+------+---------+-------------------------------------+
Один из способов ускорить процесс - использовать select count (id) from x
, что безопасно, потому что id
является первичным ключом, но я прохожу через некоторые уровни абстракции (например, NHibernate), которые делают эту задачу нетривиальной.
Я пробовал анализировать таблицу x
, но это не дало заметной разницы.
Это похоже на ] эта ошибка , хотя неясно, к каким версиям она относится и что происходит (никто не трогал ее за год, но она «серьезная / высокая / высокая»).
Есть ли какой-либо способ, кроме простого изменения моей запрос, чтобы MySQL был умнее в этом?
ОБНОВЛЕНИЕ:
По запросу, вот способ более или менее воспроизвести его. Я написал этот SQL-скрипт для генерации 1 миллиона строк фиктивных данных (выполнение занимает 10-15 минут):
выберите количество (отдельный идентификатор) из x
выберите количество (идентификатор) из x
выберите счетчик (отдельный идентификатор) из x
выберите счетчик (идентификатор) из x
EDIT:
Если я изменю запрос в 5.5, сказав
select count(distinct id) from x force index (ix_a);
, он будет выполняться намного быстрее. Индексы b и c также работают (в разной степени), и даже принудительный индекс PRIMARY
помогает.