我想知道 - 如果这段代码:
// example 1
$statement = $pdo->query('SELECT * FROM table'); // MySQL
while ($row = $statement->fetch())
{
// doing something interesting
}
相当于此代码:
// example 2
$statement = $pdo->query('SELECT * FROM table'); // MySQL
foreach ($statement as $row)
{
// doing something interesting
}
在MySQL中的无缓冲查询上下文中? (我知道循环给出相同的结果。)
或换句话说:
query
prepare
我尝试过类似的东西:
General error: 2014 Cannot execute queries while other unbuffered queries are active.
和
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$statement = $pdo->query('SELECT * FROM table WHERE x = 1');
while(...) OR foreach(...)
{
// some magic
}
OR
$statement->fetch(); // just fetch(), not fetchAll()
$statement = $pdo->query('SELECT * FROM table WHERE x = 2'); // MySQL
...
或while
代码运行没有错误。foreach
,我应该得到fetch()
。所以看来,我回答了自己的问题;)但我还是不确定。我也找不到任何可以回答我问题的文档或SO问题。
答案 0 :(得分:1)
PHP 5.5.12,Windows
我做了一些测试。我创建了一个包含100 000条记录的表,并检查了当表中的所有值用不同的方法求和时会占用多少内存:
+----------+-------------+--------+
| method | memory used | time |
+----------+-------------+--------+
| fetchAll | 69.9157 MB | 7.20 s | // <-- fails if memory_limit < 69 M
| while | 0.2494 MB | 3.24 s |
| foreach | 0.2494 MB | 0.98 s | // <-- here I disagree with Ollie
+----------+-------------+--------+
考虑到我的问题和上述测试的测试,我得出结论:
foreach
和while
等同于缓冲查询:两种方法逐行读取并在执行循环之后全部以这种方式获取数据,下一个查询不会抛出error 2014
foreach
在迭代fetchAll
之前不执行PDOStatement
之类的操作来获取整个结果集:如果确实如此,那么memory_limit < 69M
时测试会失败(恕我直言:它是相当逻辑,'因为PDOStatement
实现Traversable
接口)。所以我不同意Ollie Jones的回答(至少在我的电脑和环境中)。答案 1 :(得分:-1)
正如您所观察到的,在php foreach
中可以处理数组。因此,当您在pdo结果集上使用它时,pdo实现必须首先使结果集黯然失色。这样就完成了无缓冲的查询,并吸收了RAM。
最新版本的C#语言支持在数据流上处理foreach
的能力。但是在php中你需要使用while ($row = fetch())
构造。