2014-02-18 75 views
0

我需要更改MySQL表中几个所有权的所有权。绊倒我的是有几件相同的商品,我不想改变它们。具有限制的MySQL批量查询

现在,我与查询做这样的:

UPDATE possessions SET citizen_id=1 WHERE citizen_id=2 AND good_id=8 LIMIT 1 
UPDATE possessions SET citizen_id=2 WHERE citizen_id=4 AND good_id=2 LIMIT 1 
UPDATE possessions SET citizen_id=4 WHERE citizen_id=3 AND good_id=5 LIMIT 2 

有,有些时候,很多的这些和他们都非常相似,我觉得应该有一个办法分批提交。我可以发现,显示批量更新的示例不允许像每次更新一样设置单个限制。

你知道我可以使这个过程更快吗?

+0

您想要一个并行更新?因为有些套牌会与一些小车竞赛。如果要在不使用任何临时数据的情况下处理原始数据,那么这可能是未定义的行为。 MySQL可以做并行更新而不需要过多的查询吗? –

+0

使用临时表是不可能的。当更新的数量达到数百或数千时,我只是在寻找一些能够加速这个过程的东西。 – Luke

+0

这些查询是在单个子函数调用中吗?或者你是一个接一个地发送它们的? –

回答

0

以下方法依赖于​​表具有主键而citizen_id不属于它的事实。这里的想法:

  1. 把更新的所有参数(citizen_idgood_id要过滤的citizen_id和新值的行数更新)到一些存储,专用表,也许,或临时桌子。

  2. 分配行号到​​行上(citizen_id, good_id)分区,然后再加入排名列设置为参数表过滤的citizen_idgood_id原来全套,以及行数。

  3. 加入​​和上一次加入主键值的结果并更新citizen_id与新值。

在MySQL中的SQL,上面可能是这样的:

UPDATE possessions AS p 
INNER JOIN 
(
    SELECT 
    @r := @r * (@c = p.citizen_id AND @g = p.good_id) + 1 AS r, 
    p.possession_id, 
    @c := p.citizen_id AS citizen_id, 
    @g := p.good_id AS good_id 
    FROM 
    possessions AS p 
    CROSS JOIN 
    (SELECT @r := 0, @c := 0, @g := 0) AS x 
    ORDER BY 
    p.citizen_id, 
    p.good_id 
) AS f ON p.possession_id = f.possession_id 
INNER JOIN 
    possession_updates AS u ON u.citizen_id = f.citizen_id AND u.good_id = f.good_id 
SET 
    p.citizen_id = u.new_citizen_id 
WHERE 
    f.r <= u.row_count 
; 

possessions_update是包含参数值的表。

该查询使用已知的使用变量的行编号方法,该方法在f子查询中实现。

我没有MySQL,所以我无法从性能角度正确测试,但至少从this SQL Fiddle demo可以看出该方法的工作原理。 (UPDATE语句在模式脚本中,因为SQL Fiddle不允许在MySQL的右侧脚本中使用数据修改语句,右侧仅返回​​后的UPDATE内容。)