【问题标题】:Querying efficiently from an index table从索引表中高效查询
【发布时间】:2019-07-30 18:27:39
【问题描述】:

我有一个 MySQL 表,其中 1000 条帖子的索引如下

第一列包含关键字,第二列包含出现次数,在第三列中有一个数组,其中每个索引包含一个长度为 3 的数组,其中第一个索引表示帖子的 id,第二个索引表示出现次数在该帖子中,第三个索引包含一个行号数组,其中可以找到关键字。

现在我想创建一个搜索引擎,用户可以在其中根据关键字搜索帖子。最基本的解决方案是从 mysql 查询中获取每个关键字的所有结果,然后使用 javascript 查找所有常见的帖子 ID(就像我使用 Node 一样)。

我知道一定有办法提高效率。我想使用 MongoDB,但我不确定它是否会起作用。 而且我也不能使用弹性搜索。

【问题讨论】:

  • 为什么不规范化?
  • 我看到分贝时也有同样的反应。但是索引已由其他人完成,这就是我最终拥有的。
  • “我想使用 MongoDB” - 如果您正在考虑将数据库更改为(完全不同的),那么在同一个数据库中将其转换为更可查询的形式肯定不会关闭桌子?
  • 是的,是的,使用 python 脚本并将其转换为规范化形式。没有什么不同。
  • 这仍然有些非规范化,但应该更可查询,是的。

标签: mysql node.js mongodb indexing


【解决方案1】:

为了规范化,您可能需要至少两个表。

一个仅用于保存关键字(以及轻松快速地引用的keyword_id 值)。

“索引”的第二个表,保存 (keyword_id, post_id, line_number)。当对该索引表的简单“计数”查询可以产生相同的结果而无需与字符串数据保持同步时,保存计数的字段的存在就变得有点多余了。

然后要查找包含您的关键字的帖子,您只需执行如下查询:

SELECT i.post_id, COUNT(DISTINCT i.keyword_id) AS keywordsUsed 
FROM keywords AS k
INNER JOIN keywords_index AS i ON k.keyword_id = i.keyword_id
WHERE k.keyword IN ( 'your', 'list', 'of', 'keywords')
GROUP BY i.post_id
ORDER BY keywordsUsed DESC
;

或者这个

SELECT post_id, COUNT(DISTINCT keyword_id) AS keywordsUsed 
FROM keywords_index 
WHERE keyword_id IN (
   SELECT keyword_id 
   FROM keywords 
   WHERE keyword IN ( 'your', 'list', 'of', 'keywords')
)
GROUP BY post_id
ORDER BY keywordsUsed DESC
;

另一件值得牢记的事情是,虽然这张表感觉更大(更多行),但它可能会占用更少的实际空间(因此访问速度更快):

字符串[[113, 1, [822]], [199, 1, [11592]],[267, 1, [5293 至少为 50 个字节(假设为单字节字符集),不包括字符串本身的长度说明符。即使删除计数值和相关的逗号和空格,也只会将数据减少 9 个字节。

113, 822 199, 11592 267, 5293 是 24 字节,假设 INT 用于 id 值。

【讨论】:

  • “保存计数的字段的存在变得有点多余” - 是的,直到您需要按计数/受欢迎程度排序:) 并且快速排序,也就是说。
  • @SergioTulentsev 通过适当的索引,无论如何计算计数应该相对较快;将子计数打包到该字符串字段中仍然会更糟,并且原始设计的未打包计数是否有用是值得怀疑的,因为它可能在一篇文章中计算五个引用,其权重与五个帖子中的单个不同引用相同。我建议的设计允许相对快速地计算总体引用总数、带有引用的不同帖子以及帖子中的引用。如果确实需要更好的性能,可以创建一个汇总表。
【解决方案2】:

选择查询应该是这样的:

Select {third column name} from {table name} where {first column name} like %?%

所以如果你传入agree,你应该得到[[2,1,[673], [7,3,[303, 2863, 2866],[9,2,[...]]

这应该返回你应该能够map() over的数组

如果你想要第一个索引...

{array}.map((subArray) => subArray[0]); //returns an array of the first index

这将返回[2,7,9]

如果您尝试获取第三个索引并将它们组合起来,您应该能够执行 foreach()concat()

let sample = [];
{array}.forEach((subArray) => { sample = sample.concat(subArray);});

这将返回 `[673, 303, 2863, 2866, ...]

【讨论】:

  • 谢谢。但这就是我现在正在做的事情。我正在考虑一个更有效的解决方案。
  • 我认为提高效率的唯一方法是改变你的数据结构。
  • 是的。我必须对其进行规范化,以使其高效。
猜你喜欢
  • 2020-01-16
  • 2014-07-23
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
相关资源
最近更新 更多