mysql - 使用 PHP 加速大型文本数据和文件的算法

标签 mysql laravel algorithm large-data large-files

下面有两个表:-

  1. 文档表 - 该表包含实际包含 HTML 内容的文件的路径,并且还有一个层次结构列

  1. 查找和替换 - 此表包含要查找和替换的词(替换字符串可以是链接或 HTML 本身),其余字段是逗号分隔的 ID(表 1 中的文档 ID),它告诉要替换哪个词在哪个文档中替换

简而言之,这个过程将允许用户基于第二个表并仅在所需的文档中查找和替换关键字。

算法的工作原理如下:-

  1. 获取文档表中所有记录的计数
  2. 打破 100 条记录的集合(以减少服务器超时)
  3. 循环遍历 100 条记录,并针对此处的每条记录使用文档 ID 和层次结构 no 获取关键字列表以及要替换为该特定文档中要替换的内容(注意,where 条件运行于逗号分隔的字符串)
  4. 使用第一个表中的路径从服务器获取文件并提取 HTML 内容
  5. 按顺序对每个关键字运行循环,并根据内容中的第二个表替换为所需的内容
  6. 创建最终文件并保存在服务器上

这个过程运行良好,也给出了预期的结果。

当数据增加时,问题就开始了。目前,第一个表中有大约 50,000 个条目,因此服务器上的文件数量相同。

第二个表包含大约 15000 条查找和替换关键字的记录,长字符串以逗号分隔,文档 ID。

对于如此大量的数据,此过程将运行数天,这是不应该发生的。

数据库使用 MySQL 5.5,后端是 PHP(Laravel 5.4)。操作系统是 centos 7 和 nginx 网络服务器。

有没有办法让这个过程更顺利、更省时?感谢您的帮助。

最佳答案

php 有一个函数 shell_exec($shellCommand);

您可能希望使用名为 sed (stream editor) 的 gnu/linux shell 可访问程序执行此替换而不是将每个文件都输入 php 然后再写出来。

例如,

 $result = shell_exec
      ("cd what/ever/directory; sed 's/this/that/g' inputfile > outputfile");

会读取what/ever/directory/inputfile,将所有的this字符串改为that,并将结果写入什么/曾经/目录/输出文件。而且,与 php 相比,它的执行速度非常快。

编辑:为什么这种方法可以节省很多时间?

  • sed 这样的 Shell 程序已经存在了几十年,并且得到了高度优化。 sed 使用比 php 少得多的处理能力——少得多的 cpu 周期来完成它所做的事情。所以文件的转换速度更快。
  • 编辑文件的任务需要读取、转换和写入文件。按照您描述的方式执行此操作需要在下一个阶段开始之前完成每个阶段。另一方面,sed 是一个流编辑器。它并行读取、转换和写入所有内容。

要充分利用这种方法,您需要让您的 php 程序编写比 's/this/that/g' 更复杂的编辑命令。您将希望在单个 sed 运行中进行多次替换。您可以通过连接编辑说明来做到这一点,如下例所示:

 's/this/that/; s/blue/azul/g; s/red/rojo/g'

单个 shell 命令的长度可能约为 100K 个字符,因此您可能不会达到这些编辑指令长度的限制。

通过建议使用 sed,我确实建议使用不同的算法。

关于mysql - 使用 PHP 加速大型文本数据和文件的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52300446/

相关文章:

javascript - 使用 if 语句和查询

mysql - 如何从 MYSQL 表 TEXFIELD 中获取子字符串

php - Laravel 查询生成器 : Multiple where/orWhere and precendence of and/or

C++ 修复 OpenCV squares.cpp 示例以合并封闭的正方形

c++ - 如何查找一个点是否在一组区间内?

ruby - Eratosthenes 变体筛法

Mysql游标参数

php - 如何从数据库中获取 php session 的用户类型

php - Laravel 5.5 mysql 驱动使用两个数据库时报错

mysql - 如何将数字枚举列转换为tinyint?