子查询更新永远不会完成

时间:2013-12-17 22:13:43

标签: mysql sql sql-update subquery

我目前正在开发一个MySQL Db超过800万行的项目。我已经提供了一部分来测试它的一些查询。它有大约20列,其中5列对我有用。即:First_Name, Last_Name, Address_Line1, Address_Line2, Address_Line3, RefundID

我必须为每一行创建一个唯一但随机的RefundID,这不是问题。问题是为那些RefundID相同的行创建相同 First_Name, Last_Name, Address_Line1, Address_Line2, Address_Line3

这是我第一次与MySQL有大量行数相关的实际工作。到目前为止,我已经创建了这些查询:

-- Creating Teporary Table --
CREATE temporary table tempT (SELECT tt.First_Name, count(tt.Address_Line1) as
a1, count(tt.Address_Line2) as a2, count(tt.Address_Line3) as a3, tt.RefundID
FROM `tempTable` tt GROUP BY First_Name HAVING a1 >= 2 AND a2 >= 2 AND a3 >= 2);
-- Updating Rows with First_Name from tempT --
UPDATE `tempTable` SET RefundID = FLOOR(RAND()*POW(10,11))
WHERE First_Name IN (SELECT First_Name FROM tempT WHERE First_Name is not NULL);

此更新查询继续运行但永不结束,tempT行超过30K。然后,此查询将在主DB上运行,行数超过800K。

有人可以帮我解决这个问题吗?

此致

3 个答案:

答案 0 :(得分:1)

对我来说显而易见的解决方案......

不要使用随机值 - 使用哈希:

UPDATE yourtable
SET refundid = MD5('some static salt', First_Name
   , Last_Name, Address_Line1, Address_Line2, Address_Line3)

问题在于,如果你使用整数值作为refundId,那么很有可能发生碰撞(暗示CONV(SUBSTR(MD5(...),1,16),16,10获得一个签名的BIGINT)。但是你没有说出这个领域的类型,也没有说出“独特”这个领域的严格程度。要求是。它确实在一次通过中执行更新。

创建密集数字序列的替代方法是创建一个临时表,其中包含原始表中的唯一值和随机值。按随机值排序并设置单调递增的refundId - 然后将其用作查找表或更新原始表:

SELECT DISTINCT First_Name
   , Last_Name, Address_Line1, Address_Line2, Address_Line3
INTO temptable
FROM yourtable;

set @counter=-1;

UPDATE temptable t SET t,refundId=(@counter:=@counter + 1)
ORDER BY r.randomvalue;

还有其他解决方案 - 但效率更高的解决方案依赖于拥有多个数据副本和/或使用过程语言。

答案 1 :(得分:0)

尝试使用以下内容:

UPDATE `tempTable` x  SET RefundID = FLOOR(RAND()*POW(10,11))
WHERE exists  (SELECT 1  FROM tempT y WHERE First_Name is not NULL and x.First_Name=y.First_Name);

答案 2 :(得分:0)

在MySQL中,将joinupdate一起使用通常比使用子查询过滤where子句更有效。以下可能表现更好:

UPDATE `tempTable` join
       (SELECT distinct First_Name
        FROM tempT
        WHERE First_Name is not NULL
       ) fn
       on temptable.First_Name = fn.First_Name
    SET RefundID = FLOOR(RAND()*POW(10,11));