我有一个csv文件,其记录在第一个字段上排序。我设法生成一个函数,通过该文件进行二进制搜索,使用 fseek 进行文件随机访问。
然而,这仍然是一个非常缓慢的过程,因为当我寻找一些文件位置时,我实际上需要向左看,寻找\ n characted,所以我可以确保我正在读整行(一次整行阅读,我可以检查上面提到的第一个字段值。
这是返回包含 x 位置字符的行的函数:
function fgetLineContaining( $fh, $x ) {
if( $x 125145411) // 12514511 is the last pos in my file
return "";
// now go as much left as possible, until newline is found
// or beginning of the file
while( $x > 0 && $c != "\n" && $c != "\r") {
fseek($fh, $x);
$x--; // go left in the file
$c = fgetc( $fh );
}
$x+=2; // skip newline char
fseek( $fh, $x );
return fgets( $fh, 1024 ); // return the line from the beginning until \n
}
虽然这是按预期工作的,但我不得不感到遗憾的是我的csv文件有大约1.5Mil的行,而这些左手的搜索速度正在逐渐减慢。
有没有更好的方法在文件中寻找包含位置 x 的行?
此外,如果可以将类的对象保存到文件而不对其进行序列化,那么将会更好,从而能够逐个对象地读取文件。 php支持吗?
由于
答案 0 :(得分:1)
我认为你真的应该考虑再次使用SQLite或MySQL(就像其他人在评论中所建议的那样)。关于预计算索引的大多数建议已经在这些SQL引擎中“正确”实现。
你说SQL的速度不够好。您是否正确索引了字段?你是如何查询数据的?在哪里使用批量查询,在哪里使用预准备语句? SQL进程是否有足够的ram来将其索引存储在RAM中?
您可以尝试在当前算法下加速的一件事是将(~100MB?)文件加载到RAM光盘上。无论你选择做什么,无论是CVS还是SQLite,这都有助于加快速度,特别是如果硬盘驱动器寻找时间是你的瓶颈。
您甚至可以将整个文件读入PHP数组(假设您的计算机有足够的RAM)。这将允许您通过索引($big_array[$offset]
)查找进行搜索。
另外要记住的一点是,PHP在快速执行低级别事务方面并不是非常快。您可能需要考虑从PHP转而使用C或C ++。