我有一个大型数据集,我想在mysql上用于自动完成(> 1M记录)。
作为一个例子,我正在打字"甲醇"并希望提出类型建议..
目前我有
select AgentReferenceName as name
from tblAgentReference
where AgentReferenceName like '%methan%'
order by instr(AgentReferenceName,'methan'), char_length(AgentReferenceName)
limit 10;
这很好地完成了工作,但是有点慢
+-------------+
| name |
+-------------+
| Methan |
| Methane |
| Methane |
| Methane |
| Methanal |
| Methanol |
| Methanol |
| Methanide |
| Methanamine |
| Methanamine |
+-------------+
10 rows in set (3.52 sec)
我在该字段上有全文索引,但是当我运行通常的全文加权搜索时 - 它会碰到更大的单词,所以我得到了
select AgentReferenceName as name from tblAgentReference where match(AgentReferenceName) against ('methano*' in boolean mode) order by match(AgentReferenceName) against ('methano*') limit 10;
+----------------------------------------------------------------------------------------------------------+
| name |
+----------------------------------------------------------------------------------------------------------+
| 2,4-Methanoacridin-9-amine, 8-fluoro-1,2,3,4-tetrahydro-, 2-hydroxy-1,2,3-propanetricarboxylate (3:2) |
| 9-Amino-8-fluoro-1,2,3,4-tetrahydro-2,4-methanoacridine |
| 9-Amino-8-fluoro-1,2,3,4-tetrahydro-2,4-methanoacridine |
| 2,4-Methanoadamantane |
| 2,4-Methanoadamantane |
| 2-Amino-4,5-methanoadipate |
| 1,4-Methanoanthra(2,3-c)oxepin-7,12-dione, 1,3,4,5-tetrahydro-4,6,13-trihydroxy-3,11-dimethoxy-3-methyl- |
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4-tetrahydro- |
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4-tetrahydro- |
| 1,4-Methanoanthracene-9,10-dione, 1,2,3,4,4a,9a-hexahydro- |
+----------------------------------------------------------------------------------------------------------+
10 rows in set (0.13 sec)
所以速度很好,但结果很糟糕
我的问题 - 如何进行类似查询的快速搜索,但更接近全文的速度?
答案 0 :(得分:0)
(一些随意的想法......)
WHERE MATCH(...) AGAINST(...)
AND ... LIKE ...
首先使用FULLTEXT
进行 过滤,然后通过LIKE
进一步过滤。
但是...我对您当前的代码感到困惑。第一个示例(使用instr
)趋势从“Methan”开始选择数据。使用
AgentReferenceName LIKE 'Methan%'
假设你有INDEX(AgentReferenceName). If
AgentReferenceName is
TEXT and not
VARCHAR`,那么请考虑一个只有短名称索引的额外列。
然后考虑
( SELECT ... WHERE ... LIKE 'Methan%' ... LIMIT 10 )
UNION DISTINCT
( SELECT ... WHERE MATCH ... LIMIT 10 )
这将为您提供最多20行进行进一步排序(并削减至10行) - 可能在应用程序代码中。
答案 1 :(得分:0)
我已经处理了这个确切的问题。这就是我的所作所为。
当用户提供的自动完成字符串长度为一个或两个字符时,请忽略它。不要尝试自动填充(除非您有用户以前的搜索记录)。
当用户提供的自动填充字符串相对较短(尝试六个字符)时,请使用WHERE name LIKE CONCAT(:userstring, '%')
,从而根据用户的需要搜索字符串开始。那可以利用索引。用户可以找到她想要的字符串并选择它,然后你就完成了。
如果用户提供的字符串较长,请使用WHERE name LIKE CONCAT('%', :userstring, '%')
的其他查询。只有较长的字符串才会使用前导%
提供性能查杀功能。性能仍然会很糟糕,但该功能的使用频率会降低。
你最好的选择是,就像Rick James提到的那样,创建一个包含开始字符串的表格,其中包含您最常期望的搜索词。然后,您始终可以使用LIKE 'searchterm%'
并完全避免使用%
。
当您使用自动完成时,FULLTEXT已经发现了一些限制。