2

我有一个带有 myisam 引擎的 mysql 数据库。与许多其他表一起,我有这个表“et”,它有大约 8137037 条记录。

我已经创建了索引(列 hname 和 pnum 的单独索引,后来创建了 hname 和 pnum 的联合索引并帮助在一秒钟内执行)这样查询如下

 select st from et where hname='name' and pnum='1' limit 1

快速执行(在一秒钟内),但问题是我必须执行这个查询

select st from et where hname='name' and pnum='1' order by id limit 1

其中 id 是表的主键,此查询有时需要 145 秒 :(

我该如何解决这个问题?

表结构

mysql> describe et;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | bigint(20)  | NO   | PRI | NULL    | auto_increment |
| client_id  | int(11)     | YES  | MUL | NULL    |                |
| down_id    | bigint(20)  | YES  | MUL | NULL    |                |
| port_index | int(11)     | YES  |     | NULL    |                |
| date1      | bigint(20)  | YES  | MUL | NULL    |                |
| username   | varchar(50) | YES  |     | NULL    |                |
| hname      | varchar(80) | YES  | MUL | NULL    |                |
| pnum       | varchar(10) | YES  | MUL | NULL    |                |
| status     | int(3)      | YES  | MUL | NULL    |                |
| department | int(2)      | YES  | MUL | NULL    |                |
| comments   | text        | YES  |     | NULL    |                |
| issue      | int(1)      | YES  | MUL | NULL    |                |
+------------+-------------+------+-----+---------+----------------+
12 rows in set (0.06 sec)

索引

mysql> show indexes from et;
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
|Table| Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| et  |          0 | PRIMARY        |            1 | id          | A         |     8137037 |     NULL | NULL   |      | BTREE      |         |
| et  |          1 | status         |            1 | status      | A         |          12 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | down_id        |            1 | down_id     | A         |     4068518 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | issue_idx      |            1 | issue       | A         |     8137037 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | hname_idx      |            1 | hname       | A         |         283 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | pname_idx      |            1 | pnum        | A         |         136 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | clientid_idx   |            1 | client_id   | A         |     8137037 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | date1_idx      |            1 | date1       | A         |     8137037 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | department_idx |            1 | department  | A         |     2712345 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | hp_idx         |            1 | hname       | A         |         283 |     NULL | NULL   | YES  | BTREE      |         |
| et  |          1 | hp_idx         |            2 | pnum        | A         |        4834 |     NULL | NULL   | YES  | BTREE      |         |
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
11 rows in set (0.06 sec)

解释计划

mysql> explain select status from et where hname='mmah' and port_num='1' limit 1;
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
| id | select_type | table      | type | possible_keys                    | key          | key_len | ref         | rows | Extra       |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | error_trap | ref  | hname_idx,pname_idx,hostport_idx | hostport_idx | 96      | const,const |   37 | Using where |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
1 row in set (0.02 sec)

mysql> explain select status from et where host_name='mmah' and pnum='1' order by id desc limit 1;
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
| id | select_type | table      | type | possible_keys                    | key          | key_len | ref         | rows | Extra                       |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
|  1 | SIMPLE      | error_trap | ref  | hname_idx,pname_idx,hostport_idx | hostport_idx | 96      | const,const |   37 | Using where; Using filesort |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
1 row in set (0.00 sec)
4

2 回答 2

3

您是否尝试过创建 (id, hname,pnum) 的索引?

如果您的索引包含并且已经按 ID 排序,那么这有效地消除了这种担忧。

没有理由不能在另一个索引中包含 ID,只是因为它也是主索引。

于 2012-06-28T09:23:41.600 回答
0

在包含 hname 和 pnum 的表中创建索引。

这将导致 MYSQL 创建一个影子表,它只包含这两个参数,并且每当这两个参数在 where 中使用时,它都会在该影子表中查找,并很快找到它们。

于 2012-06-28T09:20:50.183 回答