mysql-删除具有限制的大量行(php夜间cron)

mysql-删除具有限制的大量行(php夜间cron),php,mysql,delete-row,sql-delete,Php,Mysql,Delete Row,Sql Delete,不确定处理这件事的最佳方法是什么。对于我的特殊情况,我有许多表,我想删除任何时间戳大于3个月前的行。。。aka仅保留过去3个月的记录 很简单,就是这样: //set binding cutoff timestamp $binding = array( 'cutoff_time' => strtotime('-3 months') ); //##run through all the logs and delete anything before the cutoff time

不确定处理这件事的最佳方法是什么。对于我的特殊情况,我有许多表,我想删除任何时间戳大于3个月前的行。。。aka仅保留过去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
我要从中删除的每个表都有一个时间戳列,该列被索引。我担心以后要删除的行数太多时会出现问题。在循环中限制块的最佳实践是什么?我所能想到的就是做一个初始选择,以找到是否有任何需要删除的行,然后运行删除,如果有。。。重复此操作,直到初始值未找到任何结果。这将为循环的每个迭代添加一个额外的计数查询

这里的标准/推荐做法是什么

编辑:

快速写出我的想法

//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限制,并在查询之间暂停。< /P> 还不好吗?新增要删除的列,并按上述所有要求对其进行操作


旋转桌子有很多技巧。尝试一些东西,你就会面对你的需求。

最佳实践:在需要之前不要进行优化。你的方法在任何情况下都可能非常有效。当问题变得明显时,请解决它。执行select以确定是否需要删除将使性能更差。Delete已经执行了自己的select,以查看是否需要删除。@developerwjk-没错,但是没有其他方法可以在不执行select的情况下循环使用有限的Delete查询。@Hobo Sapiens-我听到了您的意思,但在这种情况下,我宁愿先将其删除,也不愿让问题实际发生。由于我每天最多运行一次,所以即使需要,也很少有人会以有限的方式处理这些更改,这几乎不会影响性能。