【问题标题】:Optimizing MySQL table for sub-string search (one word records - dictionary)?优化 MySQL 表以进行子字符串搜索(一个单词记录 - 字典)?
【发布时间】:2015-03-10 08:29:33
【问题描述】:

如何优化约100万条记录的MySQL表进行子字符串搜索(%xxx, xx%, %xxx%)?所有记录仅包含一个单词(平均 11 个字符,最多 41 个字符)。

我知道查询 LIKE %xxx 有问题,但我不知道如何避免它。

所以问题是:有什么方法可以帮助 MySQL 尽量减少这些查询的工作量?或者有没有其他方法可以查询这些数据以不同的方式利用一些索引?

可用技术:MySQL、PHP、Javascript(MySQL 和 PHP 已在商业上使用,因此无法重新配置特定方式)。

背景:这是过去 15 年中以我的母语撰写的文学作品中使用的独特单词的“完整”列表。我想让用户有机会通过输入单词的一部分(任何部分)来找到所有相关的单词。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    您不能使用标准 MySQL 索引进行子字符串匹配。除了前缀匹配之外,它对任何东西都不起作用。

    您可能会为这个词生成一个SOUNDEX(),但这可能不是您想要的。

    您可以为每一行生成所有可能的子字符串并将它们存储在另一个表中。那将是很多行(可能是 5000 万行),尤其是如果您将单个字符作为子字符串包含在内(编辑:见下文)

    之后,您可以尝试寻找一个免费的文本匹配库来进行模糊匹配以插入到您的应用程序中。我对PHP一无所知。 FREJ 是 Java 中的东西。

    快速而肮脏的解决方案:

    1M 行 * 11 个字符 = 22MB 内存(即没有)。

    将其加载到内存中并进行扫描。

    编辑:按照建议,您可以只将子字符串和索引存储到字符串的末尾,然后使用前缀匹配来返回候选集。这将只需要每个单词 n 个索引条目,其中 n 是单词长度。

    要真正有效地使用存储,您需要了解使用 n-gram 的高级技术N-grams

    【讨论】:

    • 感谢您的快速回答。
    • 感谢您的快速回答。关于子串的想法很有趣。如果我建立所有潜在子字符串的列表......它将为我提供可以应用前缀搜索的基础......这就是如何将索引放入游戏的方式。快速检查长度总和给了我 13M 个字符。所以有 1300 万条记录。如果我将索引应用于这个新的更大的表,查询 13M 行有索引然后 1M 没有索引会更有效吗?
    • 是的 - 您可以使用前缀搜索来减小索引大小。好主意。所以这将是更少的行。索引查找应该比 1M 行上的全表扫描快得多。但是考虑一个内存搜索解决方案。
    • 内存表听起来不错,但会阻塞内存,以便长时间不受任何打击 - 我认为它效率不高。我只是想尽可能好地设计它,以尽量减少潜在的性能影响。当我将其公开时,它很容易在如此大的表上方使用全扫描查询产生过高的负载。无论如何,我喜欢你的原始想法,子字符串来自原始表,这些子字符串将成为使用索引的标准前缀查询的主题。谢谢。
    • 昨天晚上测试过。通过将所有子字符串添加到附加列中来创建具有 7M 行的表(表大小 370MB = 210MB 数据和 160MB 索引)。重要的是:现在查询该子字符串列 MySQL 利用索引,因此查询持续时间从几秒下降到几十毫秒。伟大的。非常感谢@rghome。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2013-06-22
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    相关资源
    最近更新 更多