mysql查询需要145秒

时间:2012-06-28 09:14:53

标签: php mysql

我有一个带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)

2 个答案:

答案 0 :(得分:3)

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

如果您的索引包含并且已经按ID排序,则可以有效地消除该问题。

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

答案 1 :(得分:0)

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

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