[英]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 KEY
和ENGINE
。
(在處理“添加索引怎么可能沒有效果甚至減慢查詢速度?”之前,我需要上述一些信息)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.