PHP如何在两个大文件中找出相同的记录?

本文介绍了一种在内存有限的情况下,使用PHP处理两个超过10亿行的大文件并找出其中相同记录的方法。通过分治策略,使用哈希取模将数据分散到多个小文件,然后逐个文件找出重复记录,最终合并结果。文章还提供了简化版的实操过程和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

给定a,b两个文件, 分别有x,y行数据, 其中(x, y均大于10亿), 机器内存限制100M,该如何找出其中相同的记录?

思路

  • 处理该问题的困难主要是无法将这海量数据一次性读内内存中.

  • 一次性读不进内存中,那么是否可以考虑多次呢?如果可以,那么多次读入要怎么计算相同的值呢?

  • 我们可以用分治思想, 大而化小。相同字符串的值hash过后是相等的, 那么我们可以考虑使用hash取模, 将记录分散到n个文件中。这个n怎么取呢? PHP 100M内存,数组大约可以存100w的数据, 那么按a,b记录都只有10亿行来算, n至少要大于200。

  • 此时有200个文件,相同的记录肯定在同一个文件中,并且每个文件都可以全部读进内存。那么可以依次找出这200个文件中各自相同的记录,然后输出到同一个文件中,得到的最终结果就是a, b两个文件中相同的记录。

  • 找一个小文件中相同的记录很简单了吧,将每行记录作为hash表的key, 统计key的出现次数>=2就可以了。

实操

10亿各文件太大了,实操浪费时间,达到实践目的即可。

问题规模缩小为: 1M内存限制, a, b各有10w行记录, 内存限制可以用PHP的ini_set('memory_limit', '1M');来限制。

生成测试文件

生成随机数用于填充文件:

/**
 * 生成随机数填充文件
 * Author: ClassmateLin
 * Email: [email protected]
 * Site: https://www.classmatelin.top
 * @param string $filename 输出文件名
 * @param int $batch 按多少批次生成数据
 * @param int $batchSize 每批数据的大小
 */
function generate(string $filename, int $batch=1000, int $batchSize=10000)
{
   
    for ($i=0; $i<$batch; $i++) {
   
        $str = '';
        for ($j=0; $j<$batchSize; $j++) {
   
            $str .= rand($batch, $batchSize) . PHP_EOL; // 生成随机数
        }
        file_put_contents($filename, $str, FILE_APPEND);  // 追加模式写入文件
    }
}
### PHP 中识别和调试循环代码 为了有效识别和调试PHP中的循环代码,可以采用多种方法和技术来确保代码按预期执行并排查潜在问题。 #### 使用内置函数 `debug_backtrace` `debug_backtrace()` 函数能够返回一个数组,该数组包含了调用当前函数之前的所有函数调用的信息。这有助于理解程序流以及循环的具体位置[^1]。 ```php <?php function debug_loop($i){ $backTrace = debug_backtrace(); echo "Loop iteration: {$i}\n"; var_dump($backTrace); } for ($i=0; $i<3; $i++) { debug_loop($i); } ?> ``` #### 利用日志记录工具 通过设置详细的错误报告级别并将这些信息写入文件或其他存储介质可以帮助追踪循环行为。例如: ```php error_reporting(E_ALL); // 启用所有类型的错误提示 ini_set('display_errors', 'Off'); // 关闭直接显示到浏览器 ini_set('log_errors', 'On'); ini_set('error_log', '/path/to/your/error.log'); // 循环体内部加入日志语句 foreach (range(1, 5) as $number) { error_log("Processing number {$number}"); } ``` #### 运用Xdebug扩展 安装[Xdebug](https://xdebug.org/)后可以获得更强大的调试功能,比如断点设置、变量查看等特性。这对于复杂逻辑下的循环尤其有用。启动命令如下所示: ```bash # 安装 Xdebug 扩展 pecl install xdebug echo "zend_extension=$(find /usr/lib/php -name '*xdebug*.so')" | sudo tee -a $(php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||") sudo service apache2 restart # 如果使用 Apache Web服务器的话重启服务使配置生效 ``` 之后,在IDE中配置好远程调试选项即可方便地单步执行代码并对循环部分进行深入分析。 #### 设置最大执行时间和内存限制 为了避免无限循环耗尽资源,可以通过调整PHP.ini 文件内的参数控制脚本的最大运行时间(`max_execution_time`) 和可用内存量 (`memory_limit`). 当然也可以在具体页面顶部临时修改这两个值: ```php set_time_limit(30); // 单位秒 ini_set('memory_limit','128M'); ``` 以上措施均能帮助更好地理解和优化PHP应用里的循环结构,提高开发效率的同时也增强了系统的稳定性和性能表现.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值