【问题标题】:Left weighted fast search on large text dataset - Mysql大型文本数据集的左加权快速搜索 - Mysql
【发布时间】:2017-12-05 02:35:46
【问题描述】:

我有一个大型数据集,我想在 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)

所以速度很好,但结果很糟糕

我的问题 - 如何进行快速搜索,返回类似于类似查询,但更接近全文搜索的速度?

【问题讨论】:

    标签: mysql database query-optimization


    【解决方案1】:

    (一些随意的想法......)

    WHERE MATCH(...) AGAINST(...)
      AND ... LIKE ...
    

    应该首先使用FULLTEXT过滤,然后通过LIKE进一步过滤。

    但是...我对您当前的代码感到困惑。第一个示例(使用instr倾向于选择以“Methan”开头的数据。这可以更有效地执行

    AgentReferenceName LIKE 'Methan%'
    

    假设您有 INDEX(AgentReferenceName). IfAgentReferenceNameisTEXTand notVARCHAR`,然后考虑一个仅索引短名称的额外列。

    然后考虑

    ( SELECT ... WHERE ... LIKE 'Methan%' ... LIMIT 10 )
    UNION DISTINCT
    ( SELECT ... WHERE MATCH ... LIMIT 10 )
    

    这将为您提供最多 20 行用于进一步排序(并减少到 10 行)- 可能在应用程序代码中。

    【讨论】:

    • 尝试从 tblAgentReference 中选择 AgentReferenceName 作为名称,其中 match(AgentReferenceName) 与 ('methano*' in boolean mode) AND AgentReferenceName LIKE 'methano%' order by instr(AgentReferenceName,'methan') 限制 10;给了我 1.17 秒的更快搜索 - 我想我会暂时使用这个。我稍后会尝试其他列
    【解决方案2】:

    我已经处理了这个确切的问题。这就是我所做的。

    当用户提供的自动完成字符串长度为一两个字符时,忽略它。不要尝试自动完成(除非您有用户自己之前搜索的记录)。

    当用户提供的自动完成字符串相对较短(尝试六个字符)时,请使用WHERE name LIKE CONCAT(:userstring, '%'),从而搜索以用户想要的开头的字符串。这可以利用索引。用户可能会找到她想要的字符串并选择它,然后你就完成了。

    当用户提供的字符串较长时,使用带有WHERE name LIKE CONCAT('%', :userstring, '%') 的不同查询。仅针对较长的字符串提供带有前导 % 的性能搜索。性能仍然会很糟糕,但该功能的使用频率会降低。

    您最好的办法是,就像 Rick James 提到的那样,创建一个包含字符串的表格,该表格以您最常期望的搜索词开始。然后,您始终可以使用 LIKE 'searchterm%' 并完全避免使用前导 %

    正如您所发现的,FULLTEXT 在您将其用于自动完成时有一些限制。

    【讨论】:

    • 我喜欢这个与第一个答案相结合..我认为会在 php 方面做到这一点..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多