我有两个表,我们称之为table_A和table_B。 Table_A有大约1000万行。 Table_B有3亿行。我在Table_B列X和Y上创建了索引。
更新会因为我拥有的行数而花费这么长时间,这是正常的吗?考虑到我有一个索引
,这对我来说似乎非常长这是他们的样子
表A:
ID BCODE
1 A1
2 B1
3 C1
4 D1
5 F1
表B:
X Y IDX IDY
A1 D1
D1 F1
C1 B1
Table_B有列' X'和' Y'具有在表_A&#39的列BCODE中找到的值。
我运行两个更新语句,需要9到30个小时才能完成。
Update Table_B
join table_A a on table_B.X = a.BCODE
set
table_B.IDX=a.Id ;
Update Table_B
join Table_A aa on table_B.Y = aa.BCODE
set
table_B.IDY = aa.Id ;
无论如何我可以加快速度吗?我应该补充一点,BCODE,X,Y列最长可达300个字符
以下是Explain的结果:
+----+-------------+-----------+------+---------------+-------------+---------+--------------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+-------------+---------+--------------+----------+-------------+
| 1 | SIMPLE | a | ALL | BCODE | NULL | NULL | NULL | 10238784 | NULL |
| 1 | SIMPLE | table_B | ref | relateIndex | relateIndex | 632 | test.a.BCODE | 15 | Using where |
+----+-------------+-----------+------+---------------+-------------+---------+------------+----------+-------------+
2 rows in set (0.00 sec)
答案 0 :(得分:4)
create index table_a_bcode_id on table_A(bcode, id);
覆盖索引提供索引中的查找值,避免访问表 - 使得仅索引查询成为可能。
您的查询看起来不错,但请尝试将它们合并:
update Table_B
left join table_A a1 on a1.BCODE = table_B.X
left join table_A a2 on a2.BCODE = table_B.Y
set table_B.IDX = a1.Id
table_B.IDY = a2.Id
这避免了必须两次更新行。
答案 1 :(得分:2)
从EXPLAIN输出看,Table_A.BCODE看起来没有BCODE的索引。如果你想进行JOIN,那么两个表都应该在JOIN字段上建立索引,否则由于查找的O(N)复杂性,非索引表会减慢速度。
除此之外,您已经提到两列都是长达300个字符的字符串。这些栏目的指数不是很有效。如果您可以找到一种方法来散列这些列中的值,然后通过散列值执行连接,则可以加快速度。
另一方面,对于较大的表,您应该检查索引是否适合内存。如果他们不这样做,那么MySQL将开始将您的索引交换到磁盘,这将极大地降低速度。
我们可以做一个估计:600(你的索引密钥长度)x 300M(行数)= 200 GB ......所以很可能这就是问题。
可能的解决方法:尝试对table_B进行分区(例如,通过PK),以便索引可以适合内存的每个部分(它可能意味着25个或更多分区,假设您的MySQL实例最多可以使用8 GB RAM)。