Обходной путь для отсутствующей функции нисходящего индекса в MySQL - PullRequest
2 голосов
/ 10 августа 2009

У нас есть проблема с нашей производственной средой, которая использует модифицированную версию jBPM, которая поддерживает приоритеты. Присутствующие индексы:

| JBPM_TIMER |          1 | JBPM_TIMER_DUEDATE__PRIORITY_ |            1 | PRIORITY_        | A         |           2 |     NULL | NULL   | YES  | BTREE      |         | 
| JBPM_TIMER |          1 | JBPM_TIMER_DUEDATE__PRIORITY_ |            2 | DUEDATE_         | A         |          51 |     NULL | NULL   | YES  | BTREE      |         | 

Проблемный запрос:

mysql> explain select * from JBPM_TIMER where PRIORITY_ < 0 order by PRIORITY_ ASC, DUEDATE_ desc;
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-----------------------------+
| id | select_type | table      | type  | possible_keys                 | key                           | key_len | ref  | rows | Extra                       |
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | JBPM_TIMER | range | JBPM_TIMER_DUEDATE__PRIORITY_ | JBPM_TIMER_DUEDATE__PRIORITY_ | 5       | NULL |   10 | Using where; Using filesort | 
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)

Запрос с PRIORITY_ отсортирован по возрастанию:

mysql> explain select * from JBPM_TIMER where PRIORITY_ < 0 order by PRIORITY_ ASC, DUEDATE_ asc;
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-------------+
| id | select_type | table      | type  | possible_keys                 | key                           | key_len | ref  | rows | Extra       |
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-------------+
|  1 | SIMPLE      | JBPM_TIMER | range | JBPM_TIMER_DUEDATE__PRIORITY_ | JBPM_TIMER_DUEDATE__PRIORITY_ | 5       | NULL |   10 | Using where | 
+----+-------------+------------+-------+-------------------------------+-------------------------------+---------+------+------+-------------+
1 row in set (0.00 sec)

Поиск в Google предполагает, что решением этой проблемы является добавление еще одного столбца (REVERSEPRIORITY_), который содержит значение PRIORITY_ * -1, и индексацию этого. Это кажется мне довольно уродливым решением, поэтому я хочу спросить вас, есть ли у вас лучшие!

1 Ответ

1 голос
/ 10 августа 2009

-PRIORITY - лучшее решение.

Однако вы можете использовать MySQL FORCE INDEX и STRAIGHT_JOIN для эмуляции SKIP SCAN:

SELECT  jt *
FROM    (
        SELECT  DISTINCT priority
        FROM    JBPM_TIMER
        ORDER BY
                priority DESC
        ) jtd
STRAIGHT_JOIN
        JBPM_TIMER jt FORCE INDEX (ix_JBPM_TIMER_priority_duedate)
ON      jt.priority >= jtd.priority
        AND jt.priority <= jtd.priority

Вам необходимо создать индекс для (priority, duedate):

CREATE INDEX ix_JBPM_TIMER_priority_duedate ON JBPM_TIMER (priority, duedate)

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

Я публикую это здесь только в качестве обходного пути, если вы не можете изменить свою схему.

Не используйте его, если есть малейший шанс на улучшение MySQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...