![读取 65k 行时 PHP/MySQL 挂起](https://linux22.com/image/661155/%E8%AF%BB%E5%8F%96%2065k%20%E8%A1%8C%E6%97%B6%20PHP%2FMySQL%20%E6%8C%82%E8%B5%B7.png)
我正在开发一个处理 IP 地址的 PHP 应用程序。我正在处理包含多达 40 亿行的 mysql 表。
我有一个脚本,目前需要从该表中提取 65536 个地址,当我尝试提取这 65K 行时,mysql<->php 接口无法通过 PHP 甚至 phpMyAdmin 给出响应。如果在命令行中使用,mysql 将在大约 0.2 秒内毫无问题地给出 65K 行。
包含 IP 地址的表有 3 个索引( 1 个唯一索引,2 个主索引),这些索引应该有助于提高速度,但我无法让 mysql 将关联数组返回给 PHP 以继续处理数据。
服务器是一台专用的最新 Xeon 机器,具有约 32GB 内存(我不知道确切的规格)。
有任何线索表明这里可能发生什么事吗?
提前致谢。
答案1
mysqli
并且PDO
都运行在缓冲模式默认情况下。这意味着您的查询实际上受到 PHP 进程内存限制。
从http://php.net/manual/en/mysqlinfo.concepts.buffering.php:
[在缓冲模式下],查询结果会立即从 MySQL 服务器传输到 PHP,然后保存在 PHP 进程的内存中。这样可以执行其他操作,例如计算行数和移动(查找)当前结果指针。它还允许在处理结果集时在同一连接上发出进一步的查询。缓冲模式的缺点是较大的结果集可能需要相当多的内存。
你应该php.ini
通过增加memory_limit
设置来增加 PHP 进程的内存限制,或者你可以告诉查询使用无缓冲模式:
无缓冲 MySQL 查询执行查询,然后在数据仍在 MySQL 服务器上等待获取时返回资源。这在 PHP 端占用较少的内存,但会增加服务器的负载。
Mysqli示例:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);
PDO示例:
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);