2017-09-26 39 views
0

我可以更新我用于连接的同一列吗?看起来我可以,但我的脚本崩溃了。MySQL设置JOIN ON域是否有效? “加入a = b SET a = c”

背景:我有一个旧数据库,我正在迁移。我正在通过在PHP循环中运行的大量MySQL查询处理它。循环工作人员很好,每个查询需要0.5到1 MB的内存来处理。直到它击中这个查询,突然需要什么记忆我已经分配给PHP的101%:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.category = t2.newcategory 
WHERE t1.category <> ''; 

当memory_limit的设置为128M抛出的错误是:

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted 
(tried to allocate 12288 bytes) 

当我碰到memory_limit的到256M的错误是:

PHP Fatal error: Allowed memory size of 268435456 bytes exhausted 
(tried to allocate 32768 bytes) 

但是这非常类似于查询运行得很好:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.series = t2.series_term 
WHERE t1.category <> '' AND t2.newcategory <> ''; 

PHP代码的请求:

$queries = array (
// dozens of MySQL queries here, like this: 
["Count users", 
"SELECT id from $s2.$usr;" 
], 
) 

foreach ($queries as $query){ 
    $mtime = time(); 
    $result = mysqli_query($link, $query[1]); 
    $mem = number_format((memory_get_usage()/1024/10124),2); 
    $mtime = time() - $mtime; 
    $mtime = gmdate("i:s", $mtime); 

    if ($result) { 
    $rows = number_format(mysqli_affected_rows($link)); 
    echo "<tr><td>$mtime</td><td>$rows</td><td>$query[0] — $mem Mb</td></tr>"; 
    } else { 
    $rows = mysqli_error($link); 
    echo "<tr><td>X</td><td>X</td><td>".$query[0]."<br><span style='color:red;'>".$rows."</span></td></tr>"; 
    } 
} 

有什么关于用于ON同一列使用SET非法或递归?

UPDATE:

我只是创建了两个小的测试表,并成功运行此查询:

# works 
UPDATE table1 t1 
    JOIN table2 t2 
    ON t1.column1 = t2.column1 
SET t1.column1 = t2.column2 
WHERE t1.column1 <> ''; 

更新2:

我编辑的WHERE子句,现在它在正常运行。使用0.04 Mb内存19秒:

UPDATE a.t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 
SET t1.category = t2.newcategory 
WHERE t1.category <> '' AND t1.category <> t2.newcategory; 
+0

请出示PHP代码,以及,你可能会看到'memory_limit'在'php.ini' –

+0

设置做了,而不是使用整个数据库进行更新,不能将其设置为块,例如,对于每50,000次更新,而不是一次更新查询。 – rahul

+0

Akshay Hegde,我的PHP限制设置为256M,从第一个错误后从128M提高。 – Slam

回答

0
我觉得下面的代码也会运行的很好! **这里代码:** UPDATE a.t1 INNER JOIN T2 ON t1.category = t2.oldcategory #SET t1.series = t2.series_term ##与出SET WHERE t1.category '' AND t2.newcategory''; **和t2.newcategory''**让它工作的条件越多。 我认为这是更多的条件让它工作,因为更多的条件过滤更多的数据,并让MySQL使用较少的内存。

对不起,刚刚看了你的代码,你可以不设置连接条件的数据,你会在无限循环

+0

但是你的代码中没有设置任何东西。我需要用新值更新t1.category。 – Slam

+0

你明白我的答案吗?如果你想更新t1.category,你应该添加更多的条件或增加memory_limit – Carson

+0

我写道,我已经增加了限制。无论我设置了多大的限制,该查询都使用全部内存的101%。它使用了257M,当它使用了仅仅0.5M的非常相似的查询时。而t2.newcategory没有空行。 – Slam

0

没有你t update same columns which are used in join statement. Think about the logic. It updates one row and it has to recheck the value again since it S使用相同的列加入。所以这成为无穷的递归,这将导致你的内存不足的例外。

为什么不先保存需要更新的id和键值数组中的值。 然后运行一个循环并分别更新?

SELECT t1.id,t2.newcategory from t1 
    INNER JOIN t2 
    ON t1.category = t2.oldcategory 

运行foreach循环的结果列表,并更新各行

foreach($queryResul as $row){ 
UPDATE t1 SET t1.category = $row->newcategory where t1.id = $row->id; } 
+0

为什么需要重新检查该值?我假定操作顺序首先执行JOIN ... ON,制作一个大表,然后爬行执行SET的行。那是不正确的? – Slam

+0

我不知道键值数组是什么。你能提出代码吗? – Slam

+0

“重新检查”或重新运行循环是为了防止无限递归 检查更新的答案 – BRjava

相关问题