php文件随机访问和对象到文件保存
Posted
技术标签:
【中文标题】php文件随机访问和对象到文件保存【英文标题】:php file random access and object to file saving 【发布时间】:2010-10-29 20:44:42 【问题描述】:我有一个 csv 文件,其中的记录按 第一个字段 进行排序。我设法生成了一个通过该文件进行二进制搜索的函数,使用 fseek 通过文件进行随机访问。
然而,这仍然是一个相当缓慢的过程,因为当我寻找某个文件位置时,我实际上需要向左看,寻找 \n 字符,所以我可以确保我正在阅读整行(一次整行已读取,我可以检查上面提到的第一个字段值)。
这是返回包含位置 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.5 英里的行,而且这些左搜索正在减慢速度。
有没有更好的方法在文件中查找包含位置 x 的行?
另外,如果一个类的对象可以保存到一个文件中而不用序列化它会更好,这样就可以逐个对象地读取文件。 php支持吗?
谢谢
【问题讨论】:
另外,我想到了另一个想法 - 如何对文件进行采样 - 从文件中每 1000 个条目获取一个条目并将其存储到数组中。这将产生 1500 个元素的数组,我可以对其进行二进制搜索,得到所需行的粗略近似值。然后我可以加载剩余的 1000 个元素并对它们进行二进制搜索。做同样的事情吗? 您在这个文件上执行什么样的搜索?文件是否经常更改?如果您要对同一个文件执行多次搜索,将数据加载到 SQLite 数据库并搜索数据库可能会快得多。 如果您知道平均行的长度,您可以返回一点并执行fgets()
以将指针与前一行或前几行的末尾对齐。应该足以满足二分搜索的目的。
如果文件是静态的,您可以编写一个一次性脚本来为每个 x 建立一个偏移值索引,该索引可以存储在第二个固定行大小的 .idx 文件中(简单的数学到fseek 您需要的条目在索引中的位置)并使用存储的条目作为 fseek 值在您的 CSV 文件中查找条目。
如果您以前在 mysql 中使用过它,并且对性能不满意,那么在 csv 中的任何搜索都会慢很多。正确索引的 MySQL 表总是比随机文件访问更快。
【参考方案1】:
我认为你真的应该考虑再次使用 SQLite 或 MySQL(就像其他人在 cmets 中建议的那样)。大多数关于预计算索引的建议已经在这些 SQL 引擎中“正确”地实现了。
你说 SQL 的速度不够好。您是否正确索引了这些字段?你是如何查询数据的?你在哪里使用批量查询,你在哪里使用准备好的语句? SQL 进程是否有足够的内存来将其索引存储在内存中?
您可以尝试在当前算法下加快速度的一件事是将(~100MB ?)文件加载到 RAM 磁盘上。无论您选择做什么,无论是 CVS 还是 SQLite,这都将有助于加快速度,尤其是在硬盘寻道时间是您的瓶颈时。
您甚至可以将整个文件读入 PHP 数组(假设您的计算机有足够的 RAM)。这将允许您通过索引 ($big_array[$offset]
) 查找进行搜索。
还有一件事要记住,PHP 在快速完成低级任务方面并不是超级快。您可能需要考虑放弃 PHP,转而使用 C 或 C++。
【讨论】:
好吧,这个问题的 sql 部分位于赏金问题下,位于此链接 (***.com/questions/4007671/effective-ip-location-query)。我没有mysql优化的经验,不得不说我不知道你所有的问题的答案。 我设法通过一种二分搜索使用另外 2 个附加文件来获得 3-4 倍的加速 :)以上是关于php文件随机访问和对象到文件保存的主要内容,如果未能解决你的问题,请参考以下文章