不确定处理此问题的最佳方法是什么。对于我的特殊情况,我有很多表,我想删除时间戳大于 3 个月前的任何行...也就是只保留最近 3 个月的记录。
非常简单,就像这样:
//set binding cutoff timestamp
$binding = array(
'cutoff_time' => strtotime('-3 months')
);
//##run through all the logs and delete anything before the cutoff time
//app
$stmt = $db->prepare("
DELETE
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
");
$stmt->execute($binding);
//more tables after this
我要删除的每个表都有一个已索引的时间戳列。我担心当要删除的行数很大时。限制循环中的 block 的最佳实践是什么?我能想到的就是进行初始选择以查找是否有任何需要删除的行,然后运行删除(如果有)...重复直到初始找不到任何结果。这会为循环的每次迭代添加一个额外的计数查询。
这里的标准/推荐做法是什么?
编辑:
快速写下我的想法
//set binding cutoff timestamp
$binding = array(
'cutoff_time' => strtotime('-3 months')
);
//set limit value
$binding2 = array(
'limit' => 1000
);
//##run through all the logs and delete anything before the cutoff time
//get the total count
$stmt = $db->prepare("
SELECT
COUNT(*)
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
");
$stmt->execute($binding);
//get total results count from above
$found_count = $stmt->fetch(PDO::FETCH_COLUMN, 0);
// loop deletes
$stmt = $db->prepare("
DELETE
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
LIMIT :limit
");
while($found_count > 0)
{
$stmt->execute( array_merge($binding, $binding2) );
$found_count = $found_count - $binding2['limit'];
}
最佳答案
这取决于您的表大小及其工作负载,因此您可以尝试一些迭代:
只需删除超过 3 个月的所有内容即可。看看时机是否足够好。是否存在性能下降或表锁?您的应用如何处理数据删除期?
如果一切都不好,请考虑删除 10k 左右的限制。按照上面的方法检查一下。添加适当的索引
即使它仍然很糟糕,请考虑在删除之前选择 PK,而不是在 PK 上删除 10k 限制并在查询之间暂停。
还是很糟糕?添加新列“要删除”,并按照上述所有要求对其进行操作。
旋转 table 有很多技巧。尝试一些东西,你就会面对你的需求
关于php - mysql - 删除有限制的大量行(php nightly cron),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28288216/