【发布时间】:2019-07-24 21:34:01
【问题描述】:
您在 Mysql 表中有大量非常短(
选择的项目可以少至一个(或无),多至 1M+,因此必须分析的文本大小可能会有很大差异。
目前的解决方案包括:
- 将选定记录中的文本读取到文本变量中
- preg_replacecing 删除所有不是“单词”的东西,得到一些清理,较短的文本(主题标签、@mentions、http(s):// 链接、电话号码等数字序列等不是“单词”并被解析出来)
- 将剩余的内容分解到“缓冲区”数组中
- 取出短于两个单词的所有内容并将其他所有内容转储到“主”数组中
然后用array_count_values转换结果数组,排序(arsort),第一次拼接以获得更易于管理的数组大小,然后针对几种语言的停用词列表进行解析,再处理和拼接,最后以JSON形式输出为50 个最常用词的列表。
通过跟踪操作序列的各个步骤的时序,最明显的瓶颈在于查询,但随着项目数的增加,它迅速移动到 array_count_values 函数(之后的一切都是或多或少直接)。
在大约 10k 个项目的测试运行中,从开始到结束的总执行时间约为 3 秒;有 20k 个项目需要约 7 秒。
具有 130 万个项目的(相当极端但并非不可能)案例需要 1m 用于 mysql 查询,并且能够每分钟解析大约 75k 个项目(因此估计为 17 分钟左右)。
结果应该被可视化为 AJAX 调用的结果,因此在这种时间安排下,UX 显然被打乱了。我正在寻找尽可能优化一切的方法。 30 秒的加载时间可能是可以接受的(但不太现实),10 分钟(或更多)则不是。
我尝试通过 array_count_values 对块进行批处理,然后通过键将生成的计数数组添加到主数组中,但这仅能起到很大的帮助 - 各部分的总和是相等的(或略大于)时间上的总数。
- 我只需要列表顶部出现频率最高的 50 个,因此可能有一些改进的余地,可以减少一些角落。
【问题讨论】:
-
字数很多,可以提供帮助,但少量的上下文代码通常更有价值。
-
你走错路了。与其在每个 ajax 请求中尝试读取所有数据库、检查替换、排序等,不如一劳永逸地构建一个带有计数列的单词表,并在每次插入或删除时更新它(使用触发器)。然后,您可以通过带有 LIMIT 和 ORDER BY 子句的简单查询获得结果。 (显然不到 1 秒)
-
@tadman 我一般同意,但代码不是这里的范围。找到不同的观点来解决问题是。代码如下。
-
@CasimiretHippolyte 就是我在上面的评论中提到的那种“不同的视角”。我想到了类似的东西,但是从中得出计数的出现列表的内容可能会因执行的每个查询而异 - 所以它不仅仅是“计算该表中列中的单词” - 记录可能必须匹配一些要包含在计数中的参数。
-
@tadman 我研究了这些,并且-尽管这种解决方案最终需要在相对较短的时间内集成-两者似乎都非常适合该问题(如一切都扩大了,mysql中的全文-boolean-搜索也开始迅速变薄)从文档中可以看出,对于任何一种解决方案来说,诸如单词(出现)计数之类的东西都太低级了。它可能可以完成,但不是立即的。