使用“优化MySQL搜索”;例如;和通配符

使用“优化MySQL搜索”;例如;和通配符,mysql,optimization,wildcard,Mysql,Optimization,Wildcard,你怎么能这样 SELECT * FROM sometable WHERE somefield LIKE '%value%' 优化 这里的主要问题是第一个通配符,它阻止DBMS使用索引 编辑:此外,somefield值是实心字符串(不是一段文本),因此无法执行全文搜索。使用。“初始想法”标题具有相同的示例,并导致工作示例解决方案 编辑:它不能在SQL本身中进行调优。使用诸如LOCATE或PATINEX之类的函数也不会有什么帮助。鉴于通配符的问题,这不会产生很大的影响,但不使用“SELECT*”

你怎么能这样

SELECT * FROM sometable WHERE somefield LIKE '%value%'
优化

这里的主要问题是第一个通配符,它阻止DBMS使用索引

编辑:此外,somefield值是实心字符串(不是一段文本),因此无法执行全文搜索。

使用。“初始想法”标题具有相同的示例,并导致工作示例解决方案


编辑:它不能在SQL本身中进行调优。使用诸如LOCATE或PATINEX之类的函数也不会有什么帮助。

鉴于通配符的问题,这不会产生很大的影响,但不使用“SELECT*”将提高查询性能。如果您没有实际使用返回的所有字段,则这是一个胜利,“选择*”会触发两个查询,一个查询查找表中的字段,然后使用添加的字段名进行查询。

两种方式:

(1) 使用内存中的表,使其运行得非常快

(2) 制作一个比像“%bar%”这样的foo更好的索引和搜索算法。如果不了解你的问题,就不可能对此提出任何建议


正如您所指出的,%bar%模式保证对每次查找进行表扫描,这会使数据库软件中任何可能的搜索功能无效。

字符串有多长

如果它们相对较短(例如英语单词;avg_len=5),并且您有多余的数据库存储,请尝试以下方法:

  • 对于要存储在表中的每个单词,取而代之的是该单词的所有可能后缀。换句话说,您将不断剥离第一个字符,直到什么都没有留下。例如,单词
    value
    给出:
    • value
    • lue
    • ue
    • e
  • 将这些后缀存储在数据库中
  • 您现在可以使用
    搜索子字符串,如'alu%'
    (将'alu'作为'value'的一部分查找)
通过存储所有后缀,您不需要使用前导通配符(允许使用索引进行快速查找),但需要占用存储空间

存储成本

存储单词所需的字符数变为
word\u len*word\u len/2
,即每个单词的单词长度为二次。以下是各种字号的增长系数:

  • 三个字母的单词:
    (3*3/2)/3=1.5
  • 五个字母的单词:
    (5*5/2)/5=2.5
  • 七个字母的单词:
    (7*7/2)/7=3.5
  • 12个字母的单词:
    (12*12/2)/12=6
存储单词所需的行数从1增加到
word\u len
。注意这个开销。应将附加列保持在最小值,以避免存储大量冗余数据。例如,最初在其上找到单词的页码应该可以(想想unsigned smallint),但单词上的大量元数据应该按每个单词存储在单独的表中,而不是针对每个后缀

注意事项

在拆分“单词”(或片段)时存在一种权衡。作为一个真实的例子:我们如何处理连字符?我们是将形容词
五个字母
存储为一个单词还是两个单词

权衡如下:

  • 任何被分解的元素都无法作为单个元素找到。如果我们分别存储
    five
    letter
    ,则搜索
    five letter
    fiveletter
    将失败
  • 任何未被分解的东西都会占用更多的存储空间。记住,储藏室 需求在字长上呈二次增长
为方便起见,您可能需要删除连字符并存储
fiveletter
。现在可以通过搜索
five
letter
fiveletter
找到该单词。(如果您也从任何搜索查询中去掉连字符,用户仍然可以成功地找到
五个字母


最后,有一些存储后缀数组的方法不会产生太多开销,但我还不确定它们是否能很好地转换到数据库。

实际上,我不需要在文本中找到特定的单词。我需要在值中找到子字符串(我将更新问题以澄清这一点)。整词与否无关紧要:您无法优化此查询。可能存在比优化查询更复杂的解决方案,以更快地执行此类型的搜索。如果您需要查找值中的子字符串,则可能需要调整数据库设置,以便为您提供更好的选择。你能提供一些你实际使用的数据/查询的例子吗?这是一个很好的答案,也是唯一能解决问题的答案。(无可否认,它有一个限制,即字符串必须足够短,您不介意将行数乘以平均字符串长度,但这可能是不可避免的。)现在是2020年,我正在考虑使用您的解决方案。你有更新吗?此外,是否必须为每个字符串截断列创建索引?如果是,查询是什么样子的?在聊天中回答:。还可以通过为每个字符串存储一组3字符的英文来查看ElasticSearch(向下滚动到“如何工作”)的方式。这是一种可比较的方法,但具有明显的优势,即存储成本在字长上是线性的,而不是二次的。它以更复杂的查找逻辑为代价,并且从技术上讲,降低了对查找性能的保证(由于潜在的误报)。