【问题标题】:mysql query takes 145 secondsmysql查询需要145秒
【发布时间】:2012-06-28 09:14:53
【问题描述】:

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

【问题讨论】:

标签: php mysql


【解决方案1】:

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

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

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

【讨论】:

  • 进一步了解dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html“在某些情况下,MySQL 可以使用索引来满足 ORDER BY 子句,而无需进行任何额外的排序。”
  • 我不确定,但是否值得将这 3 个一起创建和索引,因为 id 是主键并且具有与表中的行数完全相同的不同值数量,等于8137037 和不断增长
  • 我当然希望它值得,值得一试,创建索引需要一两分钟?编辑:另请参阅mysqlperformanceblog.com/2009/09/12/3-ways-mysql-uses-indexes,了解有关优化结果集排序的更多信息您可以创建它,进行解释并查看结果,然后如果它不好,请删除索引。
  • 还有更多 mysqlperformanceblog.com/2006/09/01/… 使用 B-Tree 索引来预排序您的结果集有据可查。
  • 不幸的是,创建和删除索引是一场噩梦,这需要大约 22 分钟。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 2010-10-11
    • 2010-12-17
    • 1970-01-01
    相关资源
    最近更新 更多