У меня еще один вопрос, касающийся оптимизации индексов mysql для нашей приоритетной jBPM. Соответствующие индексы выглядят так:
| JBPM_TIMER | 1 | JBPM_TIMER_REVERSEPRIORITY__DUEDATE_ | 1 | REVERSEPRIORITY_ | A | 17 | NULL | NULL | YES | BTREE | |
| JBPM_TIMER | 1 | JBPM_TIMER_REVERSEPRIORITY__DUEDATE_ | 2 | DUEDATE_ | A | 971894 | NULL | NULL | YES | BTREE | |
| JBPM_TIMER | 1 | JBPM_TIMER_DUEDATE_ | 1 | DUEDATE_ | A | 971894 | NULL | NULL | YES | BTREE | |
JBPM задает два вопроса при получении таймеров. Первый зависит от объединенного индекса (обратный приоритет и duedate), а второй - от индекса solo duedate. Однако при добавлении сольного индекса он имеет приоритет над правильным при выполнении этого запроса:
mysql> explain select timer0_.ID_ as col_0_0_ from JBPM_TIMER timer0_ where timer0_.ISSUSPENDED_<>1 and timer0_.DUEDATE_<='2009-08-17 14:51:06' order by timer0_.REVERSEPRIORITY_ asc, timer0_.DUEDATE_ asc limit 160;
+----+-------------+---------+-------+---------------------------+---------------------------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------------------+---------------------------+---------+------+-------+-----------------------------+
| 1 | SIMPLE | timer0_ | range | JBPM_TIMER_DUEDATE_ | JBPM_TIMER_DUEDATE_ERIK_T | 9 | NULL | 971894| Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+---------------------------+---------+------+-------+-----------------------------+
1 row in set (0.00 sec)
Этот индекс необходим для другого запроса:
mysql> explain select timer0_.ID_ as col_0_0_ from JBPM_TIMER timer0_ where (timer0_.EXCEPTION_ is null) and timer0_.ISSUSPENDED_<>1 order by timer0_.DUEDATE_ asc limit 160;
+----+-------------+---------+-------+---------------+---------------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------------------+---------+------+-------+-------------+
| 1 | SIMPLE | timer0_ | index | NULL | JBPM_TIMER_DUEDATE_ | 9 | NULL | 24249 | Using where |
+----+-------------+---------+-------+---------------+---------------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
При удалении сольного индекса запрос номер 1 выполняется правильно, а запрос 2 требует файловой сортировки. При добавлении сольного индекса запрос № 2 выполняется правильно, а для запроса 1 требуется файловая сортировка.
Это нежелательное поведение можно изменить, добавив подсказку индекса к первому запросу:
explain select timer0_.ID_ as col_0_0_
from JBPM_TIMER timer0_ USE INDEX (JBPM_TIMER_REVERSEPRIORITY__DUEDATE_)
where timer0_.ISSUSPENDED_<>1 and
timer0_.DUEDATE_<='2009-08-17 14:51:06'
order by timer0_.REVERSEPRIORITY_ asc, timer0_.DUEDATE_ asc
limit 160;
Является ли подсказка единственным способом заставить MySQL правильно оптимизировать оба запроса? Или мы что-то не так делаем?