【问题标题】:Workaround for missing descending index feature in MySQLMySQL 中缺少降序索引功能的解决方法
【发布时间】:2010-11-18 07:33:57
【问题描述】:

我们的生产环境存在问题,该环境使用支持优先级的修改版 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)

谷歌搜索建议解决此问题的方法是添加另一列 (REVERSEPRIORITY_),其中包含 PRIORITY_ * -1 的值并改为索引该列。在我看来,这似乎是一个非常丑陋的解决方案,所以我想问你们是否有更好的解决方案!

【问题讨论】:

标签: mysql optimization indexing


【解决方案1】:

-PRIORITY 是最好的解决方案。

但是,您可以使用 MySQL FORCE INDEXSTRAIGHT_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)

请注意,与您最初的解决方案不同,这确实是一个丑陋的 hack,其行为可能会在 MySQL 的未来版本中发生变化。

如果您无法更改架构,我将其发布在这里只是作为一种解决方法。

如果您的MySQL 有一丝升级的机会,请不要使用它。

【讨论】:

  • 好的,感谢您的快速回答。我们已经重写了补丁,现在改用 -PRIORITY。
猜你喜欢
  • 1970-01-01
  • 2010-10-07
  • 2015-10-12
  • 1970-01-01
  • 2014-03-16
  • 2016-10-19
  • 2011-05-07
  • 1970-01-01
相关资源
最近更新 更多