2014-02-18 104 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內容。)