php - PHP 中的单词出现次数 - 缩放和优化

标签 php mysql arrays regex

您在 Mysql 表中有大量非常短(<100 个字符)到中等长度(~5k 个字符)的文本项。您需要一个可靠且快速的算法来获得所有项目中的聚合词出现次数。

选定的项目可以少至一个(或无),也可以多至 100 万+,因此必须分析的文本大小可能相差很大。

目前的解决方案包括:

  • 将选定记录中的文本读入文本变量
  • preg_replacing out everything that is not a "word"getting somewhat cleaned, shorter text (hashtags, @mentions, http(s)://links, number sequences such as phone numbers, etc. are not "words"并被解析出来)
  • 将剩下的分解成一个“缓冲区”数组
  • 取出所有短于两个单词的所有内容并将其他所有内容转储到“master”数组中

生成的数组然后用 array_count_values 进行转换,排序 (arsort),第一次拼接以获得更易于管理的数组大小,然后根据多种语言的停用词列表进行解析,处理和拼接更多,最后以 JSON 形式输出为50 个最常用词的列表。

通过跟踪操作序列各个步骤的时间,最初明显的瓶颈在查询中,但随着项目计数的增加,它迅速移动到 array_count_values 函数(之后的一切都是或多或少是直接的)。

在约 10k 个项目的测试运行中,从开始到结束的总执行时间约为 3 秒;有 20k 个项目需要 ~7s。

具有 130 万个项目的(相当极端但并非不可能)情况需要 1m 的 mysql 查询,并且能够每分钟解析大约 75000 个项目(因此估计为 17 分钟左右)。

结果应该作为 AJAX 调用的结果可视化,因此在这种时间安排下,用户体验显然被打乱了。我正在寻找尽可能优化所有内容的方法。 30 秒的加载时间可能是可以接受的(但不太现实),10 分钟(或更长时间)则不是。

我已经尝试通过 array_count_values 对 block 进行批处理,然后将生成的计数数组按键添加到主数组中,但这帮助不大 - 各部分的总和相等(或略大于)时间上的总数。

  • 我只需要列表顶部出现频率最高的 50 个,因此可能有一些改进的余地,可以删减一些。

最佳答案

  1. 将列转储到文本文件中。建议SELECT ... INTO OUTFILE 'x.txt'...
  2. (如果在 Linux 等上):tr -s '[:blank:]' '\n' <x.txt | sort | uniq -c

要获得前 50 名:

tr -s '[:blank:]' '\n' <x.txt | sort | uniq -c | sort -nbr | head -50

如果您需要调整“单词”的定义,例如处理标点符号,请参阅 tr 上的文档.您可能在使用单引号中的缩写词和短语时遇到麻烦。

一些文本清理可以(并且应该)在 SQL 中完成:

WHERE col NOT LIKE 'http%'

有些可以(也应该)在 shell 脚本中完成。

例如,这将删除@variables 和电话号码以及 0、1 和 2 个字符的“单词”:

egrep -v '^@|^([-0-9]+$|$|.$|..)$'

它可以在第一个 sort 之前的管道流中.

唯一的限制是磁盘空间。脚本中的每一步都非常快。

测试用例:

表格:176K 行,大部分是文本(包括一些换行符)

$ wc x3.txt
  3,428,398 lines  31,925,449 'words'  225,339,960 bytes

$ time tr -s '[:blank:]' '\n' <x.txt | egrep -v '^@|^([-0-9]+$|$|.$|..)$' |
              sort | uniq -c | sort -nbr | head -50
 658569 the
 306135 and
 194778 live
 175529 rel="nofollow"
 161684 you
 156377 for
 126378 that
 121560 this
 119729 with
...
real    2m16.926s
user    2m23.888s
sys 0m1.380s

够快吗?

我是通过 top 观看的.似乎最慢的部分是第一个sort . SELECT用了不到 2 秒(但是,该表可能缓存在 RAM 中)。

关于php - PHP 中的单词出现次数 - 缩放和优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57191559/

相关文章:

java - 带用户输入的插入排序 double 组 - JAVA

php - 在 PHP 中正确打印 python 脚本输出

php - 使用 php 在一页上实现多阶段表单

PHP 将 mysql 转换为 excel

MySQL 查询 : Find column where key like "Y" then use another columns unique ID to update a third column with something?

javascript - 套接字在foreach中挂起多个get调用

java - 从字符串数组中删除特定字符串

php - Laravel 路由问题与 web.php 中的路由顺序

javascript - 无符号右移函数不适用于负输入

java - 如何将 Swing 设计与类分离,以便之后代码可以轻松转换为 Android