简体   繁体   English

MySQL索引不加快更新查询怎么办?

[英]How does MySQL index not speed up update query?

I have a table located in RAM and doing some performance tests.我有一个位于 RAM 中的表并进行一些性能测试。

Let's consider a sample query, adding explain sentences along with results让我们考虑一个示例查询,添加解释语句和结果

mysql> explain update users_ram set balance = balance + speed where sub = 1;
+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | UPDATE      | users_ram | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 2333333 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set (0.00 sec)

mysql>  update users_ram set balance = balance + speed where sub = 1;
Query OK, 1166970 rows affected (0.37 sec)
Rows matched: 1166970  Changed: 1166970  Warnings: 0

As you can see, it takes 0.37 sec without index.如您所见,没有索引需要 0.37 秒。 Then I'm creating an index on the sub column, which is an int column with just two possible values of 0 and 1, and surprisingly nothing changes然后我在sub列上创建一个索引,这是一个只有两个可能值 0 和 1 的 int 列,令人惊讶的是没有任何变化

mysql> create index sub on users_ram (sub);
Query OK, 2333333 rows affected (2.04 sec)
Records: 2333333  Duplicates: 0  Warnings: 0

mysql> show index from lords.users_ram;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users_ram |          0 | user     |            1 | user        | NULL      |     2333333 |     NULL | NULL   | YES  | HASH       |         |               |
| users_ram |          1 | sub      |            1 | sub         | NULL      |           2 |     NULL | NULL   |      | HASH       |         |               |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)

mysql> explain update users_ram set balance = balance + speed where sub = 1;
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key  | key_len | ref   | rows    | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
|  1 | UPDATE      | users_ram | NULL       | range | sub           | sub  | 5       | const | 1166666 |   100.00 | Using where |
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
1 row in set (0.00 sec)

mysql>  update users_ram set balance = balance + speed where sub = 1;
Query OK, 1166970 rows affected (0.37 sec)
Rows matched: 1166970  Changed: 1166970  Warnings: 0

If I remove the index and add it again, but now using btree , it gets even more weird如果我删除索引并再次添加它,但现在使用btree ,它会变得更加奇怪

mysql> explain update users_ram set balance = balance + speed where sub = 1;
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
| id | select_type | table     | partitions | type  | possible_keys | key  | key_len | ref   | rows    | filtered | Extra       |
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
|  1 | UPDATE      | users_ram | NULL       | range | sub           | sub  | 5       | const | 1057987 |   100.00 | Using where |
+----+-------------+-----------+------------+-------+---------------+------+---------+-------+---------+----------+-------------+
1 row in set (0.00 sec)

mysql> update users_ram set balance = balance + speed where sub = 1;
Query OK, 1166970 rows affected (0.62 sec)
Rows matched: 1166970  Changed: 1166970  Warnings: 0

How could adding an index could have no effect or even slow down the query?添加索引怎么会没有效果甚至会减慢查询速度?

Let's take into account that I'm not modifying the column which is indexed, so mysql doesn't have to do an extra write operation, so really I can't get what's really happening here.让我们考虑到我没有修改被索引的列,所以 mysql 不需要做额外的写操作,所以我真的不知道这里到底发生了什么。

"table located in RAM" -- I suspect that is technically incorrect. “位于 RAM 中的表”——我怀疑这在技术上是不正确的。 The possibilities (in MySQL):可能性(在 MySQL 中):

  • The table lives on disk, but it is usually fully cached in the in-RAM "buffer_pool".该表位于磁盘上,但通常完全缓存在 RAM 中的“buffer_pool”中。

  • The table is ENGINE=MEMORY .该表是ENGINE=MEMORY But that is used only for temp stuff;但这仅用于临时的东西; it is completely lost if the server goes down.如果服务器出现故障,它将完全丢失。

    update users_ram set balance = balance + speed where sub = 1; update users_ram set balance = balance + speed where sub = 1;

The table users_ram needs some index starting with sub .users_ram需要一些以sub开头的索引。 With such, it can go directly to the row(s).这样,它可以 go 直接到行。 But...但...

It seems that there are 1166970 such rows.似乎有 1166970 行这样的行。 That seems like half the table??这似乎是桌子的一半?? At which point, the index is pretty useless.在这一点上,索引是非常无用的。 But...但...

Updating 1M rows is terribly slow, regardless of indexing.无论索引如何,更新 1M 行都非常慢。

Plan A: Avoid the UPDATE .计划 A:避免UPDATE Perhaps this can be done by storing speed in some other table and doing the + whenever you read the data.也许这可以通过将speed存储在其他表中并在您读取数据时执行+来完成。 (It is generally bad schema design to need huge updates like that.) (需要这样的大量更新通常是糟糕的架构设计。)

Plan B: Update in chunks: http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks B计划:分块更新: http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks

How the heck did you get index-type to be HASH ?你是怎么把 index-type 变成HASH的? Perhaps `ENGINE=MEMORY?也许`ENGINE=MEMORY? What version of MySQL? MySQL什么版本?

What is speed ?什么是speed Another column?另一个专栏? A constant?一个常数?

Please provide SHOW CREATE TABLE users_ram -- There are some other things we need to see, such as the PRIMARY KEY and ENGINE .请提供SHOW CREATE TABLE users_ram - 我们需要查看其他一些内容,例如PRIMARY KEYENGINE

(I need some of the above info before tackling "How could adding an index could have no effect or even slow down the query?") (在处理“添加索引怎么可能没有效果甚至减慢查询速度?”之前,我需要上述一些信息)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM