簡體   English   中英

MySQL索引不加快更新查詢怎么辦?

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

我有一個位於 RAM 中的表並進行一些性能測試。

讓我們考慮一個示例查詢,添加解釋語句和結果

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

如您所見,沒有索引需要 0.37 秒。 然后我在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

如果我刪除索引並再次添加它,但現在使用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

添加索引怎么會沒有效果甚至會減慢查詢速度?

讓我們考慮到我沒有修改被索引的列,所以 mysql 不需要做額外的寫操作,所以我真的不知道這里到底發生了什么。

“位於 RAM 中的表”——我懷疑這在技術上是不正確的。 可能性(在 MySQL 中):

  • 該表位於磁盤上,但通常完全緩存在 RAM 中的“buffer_pool”中。

  • 該表是ENGINE=MEMORY 但這僅用於臨時的東西; 如果服務器出現故障,它將完全丟失。

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

users_ram需要一些以sub開頭的索引。 這樣,它可以 go 直接到行。 但...

似乎有 1166970 行這樣的行。 這似乎是桌子的一半?? 在這一點上,索引是非常無用的。 但...

無論索引如何,更新 1M 行都非常慢。

計划 A:避免UPDATE 也許這可以通過將speed存儲在其他表中並在您讀取數據時執行+來完成。 (需要這樣的大量更新通常是糟糕的架構設計。)

B計划:分塊更新: http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks

你是怎么把 index-type 變成HASH的? 也許`ENGINE=MEMORY? MySQL什么版本?

什么是speed 另一個專欄? 一個常數?

請提供SHOW CREATE TABLE users_ram - 我們需要查看其他一些內容,例如PRIMARY KEYENGINE

(在處理“添加索引怎么可能沒有效果甚至減慢查詢速度?”之前,我需要上述一些信息)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM