Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL查询:长时间处于“init”状态_Mysql_Query Optimization - Fatal编程技术网

MySQL查询:长时间处于“init”状态

MySQL查询:长时间处于“init”状态,mysql,query-optimization,Mysql,Query Optimization,我正在对MySQL表myisam引擎执行更新,根据profiler,该引擎在“init”状态下花费了大量时间: mysql> show profile for query 2; +----------------------+-----------+ | Status | Duration | +----------------------+-----------+ | starting | 0.000057 | | checking

我正在对MySQL表myisam引擎执行更新,根据profiler,该引擎在“init”状态下花费了大量时间:

mysql> show profile for query 2;
+----------------------+-----------+
| Status               | Duration  |
+----------------------+-----------+
| starting             |  0.000057 |
| checking permissions |  0.000006 |
| Opening tables       |  0.000020 |
| System lock          |  0.000007 |
| Table lock           |  0.000005 |
| init                 | 21.911657 |
| Updating             |  0.002363 |
| end                  |  0.000009 |
| query end            |  0.000004 |
| freeing items        |  0.000051 |
| logging slow query   |  0.000003 |
| logging slow query   |  0.000002 |
| cleaning up          |  0.000005 |
+----------------------+-----------+
查询如下:

mysql> update my_table
    -> set rank = 
    ->    greatest(
    ->       @rank := if(@score = score, @rank, @rank + 1),
    ->       least(0, @score := score)
    ->    )
    -> where game=7 and zone=11 and ladder=2
    -> order by score
    -> limit 100;

Query OK, 100 rows affected (21.92 sec)
Rows matched: 100  Changed: 100  Warnings: 0
my_table | CREATE TABLE `my_table` (
  `col_e` bigint(20) NOT NULL,
  `zone` bigint(20) NOT NULL,
  `score` int(11) DEFAULT NULL,
  `game` tinyint(4) DEFAULT NULL,
  `ladder` tinyint(4) DEFAULT NULL,
  `col_d` int(11) DEFAULT NULL,
  `rank` int(11) DEFAULT NULL,
  KEY `indx_e` (`col_e`),
  KEY `zone_score` (`zone`,`score`),
  KEY `zone_d_score` (`zone`,`col_d`,`score`),
  KEY `zone_lad_score` (`zone`,`ladder`,`score`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (game)
(PARTITION p1 VALUES IN (1) ENGINE = MyISAM,
 PARTITION p2 VALUES IN (2) ENGINE = MyISAM,
 PARTITION p3 VALUES IN (3) ENGINE = MyISAM,
 PARTITION p4 VALUES IN (4) ENGINE = MyISAM,
 PARTITION p5 VALUES IN (5) ENGINE = MyISAM,
 PARTITION p6 VALUES IN (6) ENGINE = MyISAM,
 PARTITION p7 VALUES IN (7) ENGINE = MyISAM,
 PARTITION p8 VALUES IN (8) ENGINE = MyISAM,
 PARTITION p9 VALUES IN (9) ENGINE = MyISAM,
 PARTITION p10 VALUES IN (10) ENGINE = MyISAM) */
我在“where”和“order by”子句中列出的所有列上都有一个复合索引,请参见下面名为“zone_lad_score”的索引:

mysql> show indexes from my_table;
+--------------------+------------+-----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| Table              | Non_unique | Key_name        | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------------------+------------+-----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| my_table           |          1 | indx_e          |            1 | col_e        | A         |     2937401 |     NULL | NULL   |      | BTREE      |         |
| my_table           |          1 | zone_score      |            1 | zone         | A         |         217 |     NULL | NULL   |      | BTREE      |         |
| my_table           |          1 | zone_score      |            2 | score        | A         |    23499213 |     NULL | NULL   | YES  | BTREE      |         |
| my_table           |          1 | zone_d_score    |            1 | zone         | A         |         217 |     NULL | NULL   |      | BTREE      |         |
| my_table           |          1 | zone_d_score    |            2 | col_d        | A         |      123355 |     NULL | NULL   | YES  | BTREE      |         |
| my_table           |          1 | zone_d_score    |            3 | score        | A         |    46998427 |     NULL | NULL   | YES  | BTREE      |         |
| my_table           |          1 | zone_lad_score  |            1 | zone         | A         |         217 |     NULL | NULL   |      | BTREE      |         |
| my_table           |          1 | zone_lad_score  |            2 | ladder       | A         |         868 |     NULL | NULL   | YES  | BTREE      |         |
| my_table           |          1 | zone_lad_score  |            3 | score        | A         |    23499213 |     NULL | NULL   | YES  | BTREE      |         |
+--------------------+------------+-----------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
我还在“游戏”中对表进行分区,总共有10个分区。表中约有4700万条记录。表定义如下:

mysql> update my_table
    -> set rank = 
    ->    greatest(
    ->       @rank := if(@score = score, @rank, @rank + 1),
    ->       least(0, @score := score)
    ->    )
    -> where game=7 and zone=11 and ladder=2
    -> order by score
    -> limit 100;

Query OK, 100 rows affected (21.92 sec)
Rows matched: 100  Changed: 100  Warnings: 0
my_table | CREATE TABLE `my_table` (
  `col_e` bigint(20) NOT NULL,
  `zone` bigint(20) NOT NULL,
  `score` int(11) DEFAULT NULL,
  `game` tinyint(4) DEFAULT NULL,
  `ladder` tinyint(4) DEFAULT NULL,
  `col_d` int(11) DEFAULT NULL,
  `rank` int(11) DEFAULT NULL,
  KEY `indx_e` (`col_e`),
  KEY `zone_score` (`zone`,`score`),
  KEY `zone_d_score` (`zone`,`col_d`,`score`),
  KEY `zone_lad_score` (`zone`,`ladder`,`score`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (game)
(PARTITION p1 VALUES IN (1) ENGINE = MyISAM,
 PARTITION p2 VALUES IN (2) ENGINE = MyISAM,
 PARTITION p3 VALUES IN (3) ENGINE = MyISAM,
 PARTITION p4 VALUES IN (4) ENGINE = MyISAM,
 PARTITION p5 VALUES IN (5) ENGINE = MyISAM,
 PARTITION p6 VALUES IN (6) ENGINE = MyISAM,
 PARTITION p7 VALUES IN (7) ENGINE = MyISAM,
 PARTITION p8 VALUES IN (8) ENGINE = MyISAM,
 PARTITION p9 VALUES IN (9) ENGINE = MyISAM,
 PARTITION p10 VALUES IN (10) ENGINE = MyISAM) */
现在,根据MySQL文档,处于“init”状态的操作包括刷新二进制日志、InnoDB日志和一些查询缓存清理操作。可以所以,既然我没有使用InnoDB,听起来就不需要花很多时间

我想我想知道为什么这个应该使用索引的更新只影响100条记录会花费这么长时间?究竟是什么让它在“init”状态下保持这么长时间?如果我对目标记录执行选择,从我的_表中选择*,其中游戏=7,区域=11,阶梯=2,按分数限制100排序,它几乎立即返回。使用zone_d_分数索引在该表上执行类似更新不到一秒钟。什么因素可能会减慢此特定更新的速度

编辑:添加了表定义、有问题的表上所有索引的完整列表,并重命名了列以使操作更简单

编辑2:以下是最接近更新的查询的“解释”:

mysql> explain select * from my_table where game=7 and zone=11 and ladder=2 order by score limit 100;
+----+-------------+--------------------+------+------------------------------------------------+-----------------+---------+-------------+-------+-------------+
| id | select_type | table              | type | possible_keys                                  | key             | key_len | ref         | rows  | Extra       |
+----+-------------+--------------------+------+------------------------------------------------+-----------------+---------+-------------+-------+-------------+
|  1 | SIMPLE      | my_table           | ref  | zone_score,zone_d_score,zone_lad_score         | zone_lad_score  | 10      | const,const | 53952 | Using where |
+----+-------------+--------------------+------+------------------------------------------------+-----------------+---------+-------------+-------+-------------+
1 row in set (0.00 sec)

经过更多的实验后,我在表上添加了一个索引,该索引还包括我对表进行分区的列:

CREATE INDEX game_zone_ladder_score ON my_table(game,zone,ladder,score)
突然之间,更新的性能在亚秒级就好得多了。我本以为更新会像SELECTs一样利用分区,但显然不是这样


仍然希望知道MySQL在更新过程中处于“init”状态时到底在做什么,和/或为什么更新不支持分区。

有一个要求,如果使用分区,分区列必须出现在主键中。靠近底部的子弹头


尝试在a列、b列和c列上创建复合索引。通常mysql在一个查询中每个表只能使用1个索引,因此使用3个单独的索引并不能获得全部好处。根据“show indexes”命令上的“seq_in_index”列,上面显示的索引是一个复合索引。它是通过以下方式创建的:在我的表格col_b、col_c、score上创建索引my_index;您是否可以发布相应SELECT语句的解释,以查看where/order子句实际使用了哪些索引?您的数据库中有多少行?大约50000次之后,由于逻辑性太强,它的速度会减慢,还包括。。。我想说init正在解析较大和最小的函数……这是真的,但前提是您的表实际上有一个主键或唯一键。如果没有,就像我的表一样,您可以在另一列上进行分区。