我写了一个查询,它花了太多时间(32分钟),所以我尝试了其他方法来更快地找到一个。
我终于写了另一个不到5秒 问题是我不了解我的优化。
有人可以解释它是如何快得多的。
hugeTable有494 500行
smallTable1有983行
smallTable2有983行
cursor.execute('UPDATE hugeTable dst,
(
SELECT smallTable1.hugeTableId, smallTable2.valueForHugeTable
FROM smallTable2
INNER JOIN smallTable1 ON smallTable1.id = smallTable2.id
-- This select represent 983 rows
)src
SET dst.columnToUpdate = src.valueForHugeTable
WHERE dst.id2 = %s AND dst.id = src.hugeTableId;', inputId2)
-- Condition : dst.id2 = %s alone target 983 rows.
-- Combinasion of : dst.id2 = %s AND dst.id = src.hugeTableId target a single unique row.
-- This query takes 32 minutes
这是一种使用更多步骤执行完全相同的请求的方法,但速度更快:
-- First create a temporary table to hold (983) rows from hugeTable that has to be updated
cursor.execute('CREATE TEMPORARY TABLE tmpTable AS
SELECT * from hugeTable
WHERE id2 = %s;', inputid)
-- Update the rows into tmpTable instead of into hugeTable
cursor.execute('UPDATE tmpTable dst,
(
SELECT smallTable1.hugeTableId, smallTable2.valueForHugeTable
FROM smallTable2
INNER JOIN smallTable1 ON smallTable1.id = smallTable2.id
-- This select represent 983 rows
)src
SET dst.columnToUpdate = src.valueForHugeTable
WHERE dst.id = src.hugeTableId;')
-- Then delete the (983) rows we want to update
cursor.execute('DELETE FROM hugeTable WHERE id2 = %s;', inputId2)
-- And create new rows replacing the above deleled ones with rows from tmpTable
cursor.execute('INSERT INTO hugeTable SELECT * FROM tmpTable;')
-- This takes litle under 5 seconds.
我想知道为什么第一种方法需要花费很多时间。 理解这将有助于我获得新的MySql级别。
答案 0 :(得分:0)
将复合索引添加到dst
:INDEX(id2, id)
(按任意顺序)。
更多强>
案例1:
UPDATE hugeTable dst,
( SELECT smallTable1.hugeTableId, smallTable2.valueForHugeTable
FROM smallTable2
INNER JOIN smallTable1 ON smallTable1.id = smallTable2.id
)src SET dst.columnToUpdate = src.valueForHugeTable
WHERE dst.id2 = 1234
AND dst.id = src.hugeTableId;
案例2:
CREATE TEMPORARY TABLE tmpTable AS
SELECT *
from hugeTable
WHERE id2 = 1234;
UPDATE tmpTable dst,
( SELECT smallTable1.hugeTableId, smallTable2.valueForHugeTable
FROM smallTable2
INNER JOIN smallTable1 ON smallTable1.id = smallTable2.id
)src SET dst.columnToUpdate = src.valueForHugeTable
WHERE dst.id = src.hugeTableId;
在不知道MySQL版本并看到EXPLAINs
的情况下,我只能猜测它们为何如此不同......
( SELECT ... JOIN ... )
可能会也可能不会被“物化”到隐式临时表中。 (较新的版本更擅长这样做。)dst
或src
上没有足够的索引,那么'努力'的数量就是两个表大小的乘积。请注意,在案例2中,dst
要小得多。 (这可能是您正在寻找的答案。)UPDATE
可能会消除上述一些问题。它可能(或可能不)消除时间差异。如需进一步讨论,请提供
SHOW CREATE TABLE
- 针对每个表格innodb_buffer_pool_size
SHOW TABLE STATUS
- 针对每个表格EXPLAIN UPDATE ...
- 每次更新 - 至少需要5.6 ( id2 = inputId2 )
?