2009-08-10 9 views
2

Wir haben ein Problem mit unserer Produktionsumgebung, die eine modifizierte Version von jBPM verwendet, die Prioritäten unterstützt. vorhanden Indizes sind:Problemumgehung für fehlende absteigende Indexfunktion in MySQL

| 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  |   | 

Die problematische Abfrage:

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) 

Die Abfrage mit PRIORITY_ aufsteigend sortiert statt:

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) 

googeln um deutet darauf hin, dass die Lösung dieses Problems ist eine weitere Spalte hinzufügen (REVERSEPRIORITY_), die den Wert von PRIORITY_ * -1 enthält und diesen stattdessen indiziert. Das scheint mir eine ziemlich hässliche Lösung zu sein, also möchte ich euch Leute fragen, ob ihr bessere habt!

+0

Folgefrage hier: http://stackoverflow.com/questions/1256568/why-does-mysql-use-the-wrong-index – Erik

Antwort

1

-PRIORITY ist die beste Lösung.

Sie können jedoch MySQLFORCE INDEX und STRAIGHT_JOIN verwenden SKIP SCAN zu emulieren:

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 

Sie benötigen einen Index für (priority, duedate) zu erstellen:

CREATE INDEX ix_JBPM_TIMER_priority_duedate ON JBPM_TIMER (priority, duedate) 

Beachten Sie, dass im Gegensatz zu Ihrem ursprünglichen Lösung, wirklich ist ein hässlicher Hack, deren Verhalten sich in den zukünftigen Versionen von MySQL ändern kann.

ich es hier nur als Behelfslösung bin Entsendung wenn Sie nicht Ihr Schema ändern können.

Verwenden Sie es nicht, wenn es eine geringste Chance Ihres MySQL ist aufgerüstet werden.

+0

Ok, danke für die schnelle Antwort. Wir haben den Patch neu geschrieben und verwenden jetzt stattdessen -PRIORITY. – Erik

Verwandte Themen