Symfony2 / Doctrine 使 $statement->execute() 不“缓冲”所有值

2024-01-07

我有一个像这样的基本代码集(在控制器内):

$sql = 'select * from someLargeTable limit 1000';
$em = $this->getDoctrine()->getManager();
$conn = $em->getConnection();
$statement = $conn->prepare($sql);
$statement->execute();

我的困难是,当结果集只有几条记录时,内存使用情况并没有那么糟糕。我在运行之前和之后回显了一些调试信息$语句->execute();部分代码,并发现我的实现具有以下内容:

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 1000 memory: 50.917 MB

当将其从 1000 条记录增加到 10k 时,MB 使用量的差异将增长到 13 MB

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 10000 memory: 62.521 MB

最终,检索大约 50k 条记录,我接近最大内存分配:

pre-execute... rowCount :: 0 memory: 49.614 MB
post-execute... rowCount :: 50000 memory: 114.096 MB

通过此实现,我无法编写控制器(甚至是命令)来检索 CSV 数据。当然,超过 50k 的条目听起来很多,但问题在于为什么,但这不是问题所在。

我的最终问题是:是否可以告诉 DBAL/Connection 或 DBAL/Statement 在执行时将数据缓冲在 SQL 中而不是整个 PHP 中。例如,如果我有 1000 万行,只将前 10k 行发送到 PHP...让我通过以下方式查看它们@语句->fetch();当光标到达 10k 的末尾时,截断数组并从数据库中获取下一个 10k?


我刚刚遇到了同样的问题,想分享一个可能的解决方案。您的 DBAL 很可能使用 PDO 库及其PDO::MYSQL_ATTR_USE_BUFFERED_QUERY设置为 true 意味着查询中的所有结果都缓存在 mysql 端并通过 PDO 缓冲到内存中,即使您从未调用$statement->fetchAll()。为了解决这个问题,我们只需要设置PDO::MYSQL_ATTR_USE_BUFFERED_QUERYfalse 但 DBAL 没有给我们一种方法来做到这一点 - 它的 PDO 连接类受到保护,没有公共方法来检索它,并且它没有给我们一种使用方法设置属性 http://php.net/manual/en/pdo.setattribute.php在 PDO 连接上。

因此,在这种情况下,我只是使用自己的 PDO 连接来节省内存并加快速度。您可以使用您的学说数据库参数轻松实例化一个数据库,如下所示:

$dbal_conn = $this->getDoctrine()->getManager()->getConnection();
$params = $dbal_conn->getParams();
$pdo_conn = new \PDO(
  'mysql:dbname='.$dbal_conn->getDatabase().';unix_socket='.$params['unix_socket'],
  $dbal_conn->getUsername(),
  $dbal_conn->getPassword()
);
$pdo_conn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

我使用的是 unix 套接字,但 IP 主机地址也可以轻松使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Symfony2 / Doctrine 使 $statement->execute() 不“缓冲”所有值 的相关文章

随机推荐