我正在寻找一种方法,在MySQL数据库中的两个表中进行快速尽可能不完整的单词LIKE "%foo%"
查找。
假设我有两个表,Boxes和Objects,其中每个Box包含多个对象。我们想要做的是通过将搜索字符串与Box.name
或Object.name
匹配来查找框的ID(Box.id)。
为了给你一张我们正在处理的音阶图片,Boxes包含~500,000个条目,而Objects包含约200,000个条目。
每个对象都在一个Box中,而不是每个Box都包含对象。我有Box.id
,Object.id
和Object.box_id
的索引。
为什么吗
我需要快速(200ms)这样的数据,所以当用户输入搜索时我可以提供建议。数据集基本上是静态的,每年更新一次。 Box.id
永远不会改变。我正在使用初始通配符,因为匹配的单词可能不会从字符串的开头开始 - 例如,"flo"
需要建议"cake flour"
以及"flour"
。
我尝试了什么:
在两个表之间进行LEFT JOIN:
SELECT b.id, b.name, o.name FROM boxes b LEFT JOIN objects o ON (b.id = o.box_id) WHERE ((b.name LIKE "%test str%") OR (o.name LIKE "%test str%")) LIMIT 10;
搜索时间:3900ms.
将所有内容归一化为一个查找表:
SELECT n.id, n.box_name, n.object_name from lookup_table n WHERE ((n.box_name LIKE "%test str%") OR (n.object_name LIKE "%test str%")) LIMIT 10;
搜索时间:1100ms
。
摆脱那种加入显然有奇迹;但是,这仍然太慢了。理想情况下,这应该需要200毫秒或更短。有没有人对如何优化部分字匹配查询有任何见解?
答案 0 :(得分:2)
查看全文索引。你不应该使用通配符作为生产系统中的第一个字符进行查询。
不要非规范化,因为存在与此相关的其他问题,包括特殊的数据完整性问题,表格过宽导致的其他性能问题,当一对一关系变为一对多时出现问题,其他受影响的代码将会出现问题休息等。加入很好。你应该想要连接,像连接这样的数据库。当然,您应该确保您加入的字段已编入索引。
答案 1 :(得分:0)
如果这是UI中的JS应用程序,请查找执行所需操作的程序包。它们的调整速度很快,并且不依赖于SQL。