如何确定是否存在多列索引

时间:2014-06-23 20:08:11

标签: mysql indexing

this question类似,我想要做的是确定索引是否存在,但是使用多个列。例如,我有一张酒店房间的下表:

CREATE TABLE `rooms` (
 `id` mediumint(9) NOT NULL AUTO_INCREMENT,
 `res_num` int(11) NOT NULL,
 `room_id` int(11) NOT NULL,
 `date` date NOT NULL,
 `adults` tinyint(4) NOT NULL DEFAULT '0',
 `children` tinyint(4) NOT NULL DEFAULT '0',
 `young_children` tinyint(4) NOT NULL DEFAULT '0',
 `pets` tinyint(4) NOT NULL DEFAULT '0',
 `smoking` tinyint(1) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 UNIQUE KEY `room_id` (`room_id`,`date`),
 KEY `res_num` (`res_num`),
 KEY `date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=97449 DEFAULT CHARSET=utf8

我想在room_iddate上添加单个索引,前提是它已经存在。执行SHOW INDEX会产生以下输出:

mysql> show index from rooms;
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| rooms |          0 | PRIMARY   |            1 | id          | A         |       67399 |     NULL | NULL   |      | BTREE      |         |               |
| rooms |          0 | room_id   |            1 | room_id     | A         |          58 |     NULL | NULL   |      | BTREE      |         |               |
| rooms |          0 | room_id   |            2 | date        | A         |       67399 |     NULL | NULL   |      | BTREE      |         |               |
| rooms |          1 | res_num   |            1 | res_num     | A         |       67399 |     NULL | NULL   |      | BTREE      |         |               |
| rooms |          1 | date      |            1 | date        | A         |        6739 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
9 rows in set (0.01 sec)

我还可以通过执行以下操作将输出限制为有问题的列:

SHOW INDEX FROM rooms WHERE Column_name = 'room_id' OR Column_name = 'date';

但是,各列可能有自己的索引,例如上面案例中的date列。如何确定所有属于同一Key_name的多个列上存在索引?

3 个答案:

答案 0 :(得分:2)

首先,发出像

这样的命令
SHOW INDEX FROM rooms
WHERE Seq_in_index > 1 
AND Column_name IN ("id", "date")

您将获得基于多个列的索引列表,并且至少包含您需要的一个列。从结果列表中,您获取Key_name,然后对每个结果重复查询:

SHOW INDEX FROM rooms WHERE Key_name=?

如果结果中有两行,并且您需要的两列都在列表中,那么您的索引就存在。

如果有人知道如何在不依赖外部编程语言的情况下在纯SQL中执行此操作,或建议更优化的方法,请改进答案

答案 1 :(得分:2)

TimSparrow的回答确实指出了我在这里的正确方向,所以一定要提出他的答案。以下是如何在不依赖任何外部编程语言的情况下一步完成所有操作:

SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'rooms'
AND index_name = (
    SELECT index_name
    FROM INFORMATION_SCHEMA.STATISTICS
    WHERE TABLE_SCHEMA = 'db_name' 
    AND TABLE_NAME = 'rooms'
    AND Seq_in_index = 2 
    AND Column_name IN ("room_id", "date")
)
AND Column_name IN ("room_id", "date")

只需将索引包含的所有列放在Column_name部分中,然后将Seq_in_index更改为索引中的列数。如果它返回与Seq_in_index相同的值,则索引存在。

您还可以使用2列以上的内容轻松将其扩展到索引。例如,如果使用所有这些列存在索引,则以下内容将返回5

SELECT COUNT(*)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'rooms'
AND index_name = (
    SELECT index_name
    FROM INFORMATION_SCHEMA.STATISTICS
    WHERE TABLE_SCHEMA = 'db_name' 
    AND TABLE_NAME = 'rooms'
    AND Seq_in_index = 5
    AND Column_name IN ("room_id", "date", "foo", "bar", "baz")
)
AND Column_name IN ("room_id", "date", "foo", "bar", "baz")

答案 2 :(得分:1)

您可以检查使用以下语句索引的多个列,假设您不希望将多个列作为主键索引检查

select  table_schema, table_name, index_name, group_concat(column_name) column_name
from    information_schema.statistics
where   table_schema = 'your_schema'
and     index_name != 'PRIMARY'
group by table_schema, table_name, index_name
having count(column_name) > 1