插入 6000 条记录,执行时间增加 5-10 秒


Inserting 6000 records adding 5-10 seconds to the execution time

我的应用程序是一个数字标牌播放器。我们需要定期将远程播放证明数据发送回云端。缓存播放证明数据以帮助解决网络中断问题。

玩家可以在一天内轻松创建 6,000 个 POP 记录。当网络恢复时,这可能会导致从一个演示文稿移动到另一个演示文稿的严重延迟。

我正在考虑使用 MySql 的异步模式来尝试缓解这种延迟......但我不认为它做了我认为它所做的事情。

我正在循环一个大的结果集,我仍然需要等待该循环完成。我是否捆绑了 6,000 个插入物并一次发送它们?如果我仍在等待异步数据库调用,我的 AJAX 会在什么时候返回结果?这样不行吗?谷歌返回的结果不到一页,文档并没有真正揭示任何信息。

$sql = "SELECT MAX(time) from `pop` where `displayId` = ".$_GET['id'];
$res = $local->query($sql);
$row = $res->fetch_row();
//$log->lwrite("Last Updated is ".$row[0]);
$sql = "SELECT * FROM `pop` 
   WHERE `displayId` = ".$_GET['id']
   ." AND `time` > '".$row[0]."' LIMIT 1000";
$local->query($sql, MYSQLI_ASYNC);
if ($res = $local->reap_async_query()) {
    while ($row = $res->fetch_row()) {
        $log->lwrite(print_r($row, 1));
        $sql = "INSERT INTO `pop` 
          (`displayId`, `time`, `duration`, `presId`) 
          VALUES ('".$row[1]."', '".$row[2]."', '".$row[3]."', '".$row[4]."')";
        $remote->query($sql, MYSQLI_ASYNC);
    }
}

我已经接受了我将不得不以不同的方式做到这一点的想法。现在我只是好奇。:)

我在这里错过了什么吗?

感谢您的时间和帮助。

你说的是你的php服务器和DBMS之间的网络吗?在这种情况下,你真的不了解异步mysqli。

使用异步查询的目的是在不阻塞 PHP 代码的情况下应用 DML。它不打算将命令排队到可能定期脱机的系统。你也不应该直接在互联网上公开DBMS。它提供了一个窗口,您可以在其中对 php 代码执行其他操作(例如运行其他查询或将数据发送到客户端(。它不打算在脚本完成后对数据执行操作。

有很多方法可以解决这个问题,其中大多数涉及在连接的两端运行守护进程 - 这可能是大多数人的主要限制。你没有说你对两端的系统有什么控制权。一个折衷的解决方案是从卫星系统上的工作中使用。当然,您不应该尝试在 Web 请求的处理程序中复制数据。

是否正在尝试在本地复制整个表?如果是这样,为什么不使用MySQL的内置复制(通过VPN链接(。

代码的第一件事是你不应该在循环中执行你的 INSERT 语句。执行此操作的正确方法是在单个 INSERT 语句中将多个记录插入到数据库中。这仅受MySQL的max_allowed_packet设置的限制,该设置限制了查询的长度。通常这是相当大的,可以轻松容纳 6000 条记录。

$sql = "SELECT * FROM `pop` 
   WHERE `displayId` = ".(int)$_GET['id']
   ." AND `time` > '".$local->real_escape_string($row[0])."' LIMIT 1000";
$res = $local->query($sql) or die($local->error);// no async
$sql = '';
while ($row = $res->fetch_row()) {
    $row = array_map(array($local, 'real_escape_string'), $row);// must have sanitization
    if ($sql) $sql.= ',';// separate each record with a comma
    $sql.= "('".$row[1]."', '".$row[2]."', '".$row[3]."', '".$row[4]."')"
    $log->lwrite(print_r($row, 1));
}
$sql = "INSERT INTO `pop` 
  (`displayId`, `time`, `duration`, `presId`) 
  VALUES $sql";
$remote->query($sql, MYSQLI_ASYNC);// Do only one INSERT query instead of thousands

如果在此处使用 MYSQLI_ASYNC,PHP 将不会等待插入完成,并且您的 AJAX 调用将完成,而无需等待远程数据库查询完成。