mysqli_store_result() 与 mysqli_use_result()

Posted

技术标签:

【中文标题】mysqli_store_result() 与 mysqli_use_result()【英文标题】:mysqli_store_result() vs. mysqli_use_result() 【发布时间】:2012-04-10 05:28:51 【问题描述】:

问题

mysqli::store_result()mysqli::use_result() 有什么区别?

故事

模糊的文档

php.net 上的文档似乎对两者之间的区别非常模糊。 mysqli::use_result()-page 不提供任何代码示例,并将您链接到 mysqli::multi_query()-page 以查找它们。在该页面中,给出了以下代码示例(请参阅页面以获取完整代码):

/* store first result set */
if ($result = $mysqli->store_result()) 
    while ($row = $result->fetch_row()) 
        printf("%s\n", $row[0]);
    
    $result->free();

/* print divider */
if ($mysqli->more_results()) 
    printf("-----------------\n");

mysqli::store_result()-page 使用完全相同相同的代码示例,但有一个例外:

/* store first result set */
if ($result = $mysqli->use_result()) 

是的...store_result 变成了use_result。请注意,即使上面的评论仍然是“商店”。

更令人困惑

看过代码示例后,我想; “好吧,所以它是一个别名”。可是等等!文档给出了以下描述:

mysqli_store_result — 传输上一个查询的结果集 mysqli_use_result — 启动结果集检索

它们看起来像是两种不同的东西,根本不像别名一样。仔细一看,我发现mysqli::use_result()-page 的代码示例中还有另一个异常:$result->free(); 变成了$result->close();。然而,我发现真相的希望很快就破灭了,当我发现在第二个代码示例(程序等效)的同一页面上,使用了mysqli_free_result($result);,而不是预期的mysqli_close_result($result);

【问题讨论】:

【参考方案1】:

我认为这种阐述可能会帮助人们从支持通过数组或枚举器检索的语言到达这里。因为这就是区别。

对于 .NET,它与 GetDirectories (store_results) 与 EnumerateDirectories (use_results)(以及 File/DbResult/CSV parsing/XML Parsing 等效项)的区别相同。

枚举器变体使用较少的 (PHP) 客户端内存,并且可能在当前行正在处理时在后台异步获取下一行,从而使其在客户端有效的内存和处理时间都更多。以更长时间占用 (SQL) 服务器资源为代价(因为结果集尚未完全传输)。

反过来,get/array 方式将在一次阻塞操作中检索数据,占用更多客户端内存以提前释放 DB 内存。

我个人会默认使用非枚举器方式,除非您确实遇到(客户端)内存问题。

在 .NET 中,如果遇到 x32 进程的 2/3 GiB 限制,则必须使用 Enumerator 方式。文件的特定 EnumerateLines 在这里很重要。 对于数据库结果,它不应该发生在开始。 2 GiB 的 DB 结果要么是方式 过滤不足(在 Query 中进行更多过滤),要么包含大量 Blob(您应该逐个加载它们,或者如果可能的话,甚至让浏览器通过 http 处理程序检索) .

【讨论】:

【参考方案2】:

use_result 返回一个无缓冲结果。

store_result 返回一个缓冲结果。

【讨论】:

PHP 的默认方法是什么?例如,如果我在准备好的语句上的 execute() 和 fetch() 之前不执行 store_result() 或 use_result() 。我假设 use_result(),因为 mysqli_stmt 对象上没有 use_result()。 @crush NO,默认为 MYSQLI_STORE_RESULT @crush mysqli_prepare 默认为 无缓冲(使用 mysqli_stmt::store_result 或 mysqli_stmt::get_result 进行缓冲)pdo_prepare缓冲默认情况下(使用 $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false) 表示无缓冲)mysqli_querypdo_query 默认情况下缓冲【参考方案3】:

mysqli::store_result() 将从 MySQL 服务器获取整个结果集,而 mysqli::use_result() 将一一获取行。

您链接到的 mysqli::use_result 文档中也提到了这一点:

mysqli_use_result() 函数不会从数据库中传输整个结果集,因此不能使用诸如 mysqli_data_seek() 之类的函数来移动到集合中的特定行。要使用此功能,必须使用 mysqli_store_result() 存储结果集。如果在客户端执行大量处理,则不应使用 mysqli_use_result(),因为这会占用服务器并阻止其他线程更新从中获取数据的任何表。

您通常总是可以使用mysqli::store_result(),除非您有充分的理由不一次从服务器读取所有行。

【讨论】:

啊,所以基本上后续的use_result 调用要繁重得多,因为 php 必须查询服务器以获取结果集中的每个结果,而使用store_result,所有结果都将被存储在第一次调用后在 php 端,后续调用只会从 php 请求结果? 是的,总结得差不多了。 我只是喜欢 php.net 上带有评论 If we have to retrieve large amount of data we use MYSQLI_USE_RESULT 的示例,什么被归类为 large amount of data?这个术语是非常相对的。说亚马逊的数据库中的少量数据会比我整个 5 Mb 的数据库大。 好的,那么get_result 是做什么的? @amaster507 刚刚在返回值部分的mysqli::store_result() 页面上发现了有趣的注释:... returning FALSE after successful call to mysqli_query() can be too large result set (memory for it cannot be allocated) 这意味着如果您没有足够的内存来缓冲所有预期的数据,您应该使用mysqli::use_result()跨度>

以上是关于mysqli_store_result() 与 mysqli_use_result()的主要内容,如果未能解决你的问题,请参考以下文章

PHP的mysqli_query参数MYSQLI_STORE_RESULT和MYSQLI_USE_RESULT的区别

mysqli_query 的用法和my_sqliconnect的用法

数字信号处理相关函数与线性卷积关系 ( 卷积概念 | 相关函数概念 | 相关函数与线性卷积对比 | x(-m) 共轭 与 y(m) 的卷积就是两个信号 位移 m 的相关函数 )

m与n的数学运算

ValueError: 时间数据 '' 与格式 '%Y-%m-%d %H:%M' 不匹配

访问与 LINESTRING M 和 MULTILINESTRING M 几何相关的 M 值