【问题标题】:Two indexes with same field in MySQL tableMySQL表中具有相同字段的两个索引
【发布时间】:2016-04-01 07:36:47
【问题描述】:

例如我们有表:

CREATE TABLE `my_tbl` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `id_type` int(11) NOT NULL,
 `date` date NOT NULL,
 `other_fields` varchar(200) CHARACTER SET latin1 NOT NULL,
 PRIMARY KEY (`id`),
 KEY `id_type` (`id_type`),
 KEY `type_date` (`id_type`,`date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8

有两个索引:id_typeid_type, date

据我所知,如果我们有两个字段的索引,我们可以将其用作第一个字段的单个索引。

我可以删除索引 id_type 而不损失性能吗?

更新:问这个问题的原因是注意到有时不同索引中的相同字段具有不同的基数。

【问题讨论】:

  • 是的,你可以删除它。

标签: mysql performance indexing


【解决方案1】:

MySQL 5.7.9 - 删除 id_type 索引并没有什么不同。多列索引(type_date)适用于两个查询。

解释查询输出:

mysql> explain SELECT id_type,date FROM my_tbl WHERE id_type='some';
+----+-------------+--------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | my_tbl | NULL       | ref  | type_date     | type_date | 4       | const |    1 |   100.00 | Using index |
+----+-------------+--------+------------+------+---------------+-----------+-----



mysql> explain  SELECT id_type FROM my_tbl WHERE id_type='some';
+----+-------------+--------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
        +----+-------------+--------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | my_tbl | NULL       | ref  | type_date     | type_date | 4       | const |    1 |   100.00 | Using index |
        +----+-------------+--------+------------+------+---------------+---------


mysql> show indexes from my_tbl;
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| my_tbl |          0 | PRIMARY   |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| my_tbl |          1 | type_date |            1 | id_type     | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| my_tbl |          1 | type_date |            2 | date        | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+-------------

【讨论】:

  • 这很有趣。您可以尝试运行相同的查询,也只添加单列的索引并发布结果吗?
  • @Starx:即使同时存在单列索引和多列索引,也会应用相同的“type_date”索引
【解决方案2】:

INDEX(a), INDEX(a, b) -- 放弃前者,因为后者可以使用。

同时使用会浪费磁盘空间并减慢插入速度(有点)。

INDEX(a, c), INDEX(a, d) -- 你可能会发现这两个都很有用。

UNIQUE(a), INDEX(a, b) -- 现在,由于唯一性约束,需要前者。放弃后者。

另一方面...INDEX(a, b)(在我的两个例子中)可能如果它是一个“覆盖”索引特别有用。也就是说,如果 SELECT 触及 both ab 以及 no 其他列。在这种情况下,查询完全在索引结构(BTree)中执行,不必触及数据结构。

More info.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2013-12-23
    • 1970-01-01
    相关资源
    最近更新 更多