我们的生产环境存在问题,该环境使用支持优先级的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)
谷歌搜索表明,解决这个问题的方法是添加另一个包含PRIORITY_ * -1值的列(REVERSEPRIORITY_)并将其作为索引。在我看来,这似乎是一个非常丑陋的解决方案,所以我想问问大家是否有更好的解决方案!
答案 0 :(得分:1)
-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
升级的可能性很小,请不要使用它。