Mysql 5.7不要使用索引

时间:2016-03-07 08:53:55

标签: mysql indexing percona

你好,因为我从mysql 5.5更新到percona 5.7

此查询:

SELECT COUNT(a.alarm_id) AS `count`, MAX(a.alarm_id) AS `max_alarm_id`, `a`.`priority` 
    FROM `alarm` AS `a` 
    WHERE (a.maintenance_suppress = '0') 
    AND (a.deleted_at = '0000-00-00 00:00:00') 
    AND (a.object_id = '6') 
    GROUP BY `a`.`priority`

不再按预期使用索引。

这是查询的解释:

+----+-------------+-------+------------+------+---------------------------------------------------------------------+-----------+---------+-------------------+------+----------+--------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys                                                       | key       | key_len | ref               | rows | filtered | Extra                                                  |
+----+-------------+-------+------------+------+---------------------------------------------------------------------+-----------+---------+-------------------+------+----------+--------------------------------------------------------+
|  1 | SIMPLE      | a     | NULL       | ref  | maintenance_suppress,alarm_count,deleted_at,object_id,alarm_count_b | object_id | 10      | const,const,const |    1 |   100.00 | Using index condition; Using temporary; Using filesort |
+----+-------------+-------+------------+------+---------------------------------------------------------------------+-----------+---------+-------------------+------+----------+--------------------------------------------------------+

这是我的索引:

Keyname                 Type    Unique  Packed  Column                      Cardinality Collation   Null
PRIMARY                 BTREE   Yes     No      alarm_id                    1156170     A           No  
quited_by               BTREE   No      No      acknowledged_by                  78     A           Yes 
deleted_by              BTREE   No      No      deleted_by                        9     A           Yes 
device_id               BTREE   No      No      component_id                    820     A           Yes 
message_status_create   BTREE   No      No      message_status_create             2     A           No  
leaved_at               BTREE   No      No      leaved_at                    597481     A           No  
                                                message_status_leaved        527117     A           No
acknowledged_at         BTREE   No      No      acknowledged_at              139029     A           No  
                                                message_status_acknowledged  176719     A           No
maintenance_suppress    BTREE   No      No      maintenance_suppress              1     A           No  
ticket_id               BTREE   No      No      ticket_id                         1     A           Yes 
alarm_count             BTREE   No      No      priority                          5     A           No  
                                                specified_class                   8     A           No
                                                maintenance_suppress              8     A           No
                                                deleted_at                    27340     A           No
                                                object_id                     21310     A           No
deleted_at              BTREE   No      No      deleted_at                    29538     A           No  
specified_class         BTREE   No      No      specified_class                   2     A           No  
created_at              BTREE   No      No      created_at                   876796     A           No  
object_id               BTREE   No      No      object_id                       192     A           No  
                                                deleted_at                    10261     A           No
                                                maintenance_suppress          56175     A           No
alarm_count_b           BTREE   No      No      priority                          6     A           No  
                                                maintenance_suppress              9     A           No
                                                deleted_at                    31421     A           No
                                                object_id                     46226     A           No

如果我强制索引它会变慢:

mysql> SELECT COUNT(a.alarm_id) AS `count`, MAX(a.alarm_id) AS `max_alarm_id`, `a`.`priority` 
    ->     FROM `alarm` AS `a` 
    ->     WHERE (a.maintenance_suppress = '0') 
    ->     AND (a.deleted_at = '0000-00-00 00:00:00') 
    ->     AND (a.object_id = '68') 
    ->     GROUP BY `a`.`priority`;
+-------+--------------+----------+
| count | max_alarm_id | priority |
+-------+--------------+----------+
|     8 |      1278404 |        2 |
+-------+--------------+----------+
1 row in set (0.01 sec)

mysql> SELECT COUNT(a.alarm_id) AS `count`, MAX(a.alarm_id) AS `max_alarm_id`, `a`.`priority` 
    ->     FROM `alarm` AS `a` FORCE INDEX (alarm_count_b)
    ->     WHERE (a.maintenance_suppress = '0') 
    ->     AND (a.deleted_at = '0000-00-00 00:00:00') 
    ->     AND (a.object_id = '68') 
    ->     GROUP BY `a`.`priority`;
+-------+--------------+----------+
| count | max_alarm_id | priority |
+-------+--------------+----------+
|     8 |      1278404 |        2 |
+-------+--------------+----------+
1 row in set (0.67 sec)

有谁知道我的索引有什么问题?

SQL小提琴玩arround: http://sqlfiddle.com/#!9/23949/1

2 个答案:

答案 0 :(得分:1)

怀疑升级可能产生影响的原因是它在执行升级时已经完成了一个ANALYZE TABLE,因此现在从更新的统计信息中选择一个索引。

现在使用的索引对于WHERE子句中的列似乎更合乎逻辑。索引中的所有3列都在WHERE子句中使用。 alarm_count_b索引具有在索引开头用于GROUP BY的列,但这只有在WHERE子句排除记录后才真正有用。

但是,尝试在object_id索引的末尾添加优先级作为额外的列。

答案 1 :(得分:0)

你还没有说5.5对5.7的影响。在任何情况下,您都没有最佳索引,因此我将回答该问题。

WHERE (a.maintenance_suppress = '0') 
AND (a.deleted_at = '0000-00-00 00:00:00') 
AND (a.object_id = '6') 
GROUP BY `a`.`priority`
除非INDEX(maintenance_suppress, deleted_at, object_id, priority)必须最后,否则

以任何顺序请求priority。建议您将priority添加到INDEX object_id

作为一般规则,以<{1}}条件启动,然后转移到=中的一个范围条件。如果WHERE已完成,那么<​​em>一个范围可以是WHEREGROUP BY的所有字段。

More discussion of index building

另一个说明。假设您正在使用InnoDB,ORDER BY将成为该索引的一部分,从而使其“覆盖”。这提供了额外的提升。 alarm_id也涵盖了,但列没有按最佳顺序排列,因此表现不佳。

在没有看到您的其他查询的情况下,我无法判断其余的索引,除了说14个索引“很多”。