【问题标题】:Odd behavior when fetching 100K rows from MySQL via PHP通过 PHP 从 MySQL 获取 100K 行时的奇怪行为
【发布时间】:2012-06-01 09:40:31
【问题描述】:

在这里寻找一些想法...我有一个 MySQL 表,其中包含 100K 行测试数据。

我正在使用 PHP 脚本从该表中获取行,在这个测试案例中,该脚本正在获取所有 100,000 行(对大型数据集进行一些分析和优化)。

我连接到数据库,并执行一个无缓冲的查询:

$result = mysql_unbuffered_query("SELECT * FROM TestTable", $connection) or die('Errant query:  ' . $query);

然后我迭代结果:

if ($result) {
    while($tweet = mysql_fetch_assoc($result)) {
        $ctr++;

        if ($ctr > $kMAX_RECORDS) {
            $masterCount += $ctr;
            processResults($results);
            $results = array();
            $ctr = 1;
        }

        $results[] = array('tweet' => $tweet);
    }

    echo "<p/>FINISHED GATHERING RESULTS";
}

function processResults($resultSet) {
    echo "<br/>PROCESSED " . count($resultSet) . " RECORDS";
}

$kMAX_RECORDS = 40000 现在,所以我希望看到如下输出:

已处理 40000 条记录
已处理 40000 条记录
已处理 20000 条记录

完成收集结果

但是,我一直看到:

处理了 39999 条记录
已处理 40000 条记录

完成收集结果

如果我在 $ctr++ 之后立即添加 $ctr 的输出,我会得到完整的 100K 记录,所以在我看来,这似乎是某种时间问题或使用 MYSQL_FETCH_ASSOC 从后端获取数据的问题。

在一个相关的注释中,while 循环中的代码在那里,因为在像这样分解 $results 数组之前,while 循环会在大约 45000 条记录(每次都在同一个地方)时失败。这是因为我错过了某个地方的设置吗?

感谢您的任何意见...只是需要一些想法来寻找这个问题的答案。

干杯!

【问题讨论】:

  • 请停止使用古老的mysql_* 函数编写新代码。它们不再维护,社区已经开始 deprecation process 。相反,您应该了解prepared statements 并使用PDOMySQLi。如果您无法决定,this article 将帮助您选择。如果你想学习,here is a good PDO-related tutorial.
  • 这和问题有关系吗?我不需要学究式的 cmets,而是需要对所提出的问题有所了解。
  • 不是真的,因此它是评论而不是答案。这不是迂腐(或无意),我认为那里有一些有趣的阅读可能会有所帮助。拿走还是留给你。

标签: php mysql large-data-volumes


【解决方案1】:

当您开始查看结果时,$ctr 没有任何值,并且执行第一次递增会将其评估为 0。但是当达到 $kMAX_RECORDS 时,您将其重置为 1 而不是 0。但是我不知道您为什么会看到第一次调用processResults()时少了1行。我觉得应该再多一个。

至于缺少最后 20000 行,请注意您仅在 $ctr 超过 $kMAX_RECORDS 之后才运行 processResults()

【讨论】:

  • 感谢 Zefiryn,解决了柜台问题,现在得到了预期的结果。关于为什么 while 循环会在 45000 条左右的记录之后失败的任何想法?
  • @Raconteur 你可能会打到memory_limitmax_execution_time
  • 干杯,瓦斯科,会检查这些。
  • memory_limit @ 128M, max_execution_time = 60。大约 10s 后它会掉下来,并且总是在第 42563 条记录(没有特殊特征),在数组中大约 6MB。
  • 尝试设置 ini_set('display_errors', 1);并查看是否有任何错误报告。或者查看错误日志
【解决方案2】:

您正在构建一个结果数组,并计算该新数组的成员。所以是的,在获取第一行后,您会得到“1 个结果”,然后是“2 个结果”,等等……

如果您想获得预期的总行数,您需要使用mysql_num_rows()

【讨论】:

  • 你是不是错过了使用mysql_的强制性骂声?大声笑:)
  • 不,我不费心去竖琴。如果您知道自己在做什么,使用 mysql_ 函数编写与使用 pdo/mysqli 一样安全(甚至更安全)。
  • 我支持你,兄弟......以及其他标准“你需要重新设计你曾经做过的一切,以正确的方式去做”,哈哈
  • @MarcB 要获得与 PDO 等安全级别相同的 mysql_* 样式代码,将需要 代码。此外,明确不鼓励在 php.net 上使用 mysql_* 函数,并且已经有许多关于即将弃用的讨论。推广使用这些功能并不是一个好主意,无论您认为它们的安全性与更现代的 API 相比如何。
  • 是的,mysql_ 函数将是 PHP 的 Windows XP - 在应该执行的时候挂在 farrrrrr 上。那里有太多的代码取决于它。并且使用 PDO 绝对不能保证编写“安全”的查询。一个白痴可以像使用任何其他 DB 接口一样将自己注入 PDO。
猜你喜欢
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 2011-09-10
  • 2017-03-10
  • 1970-01-01
  • 2017-06-23
  • 2015-05-13
  • 2015-09-03
相关资源
最近更新 更多