如何在多列上加速SELECT .. LIKE查询?

Tom*_*Tom 44 mysql sql-like

我有一个MySQL表,我经常SELECT x, y, z FROM table WHERE x LIKE '%text%' OR y LIKE '%text%' OR z LIKE '%text%'查询.任何类型的索引都能帮助加快速度吗?

表中有几百万条记录.如果有任何可以加速搜索的内容,是否会严重影响数据库文件的磁盘使用率INSERT以及DELETE语句的速度?(没有UPDATE执行过)

更新:发布后很快,我看到了很多关于LIKE查询中使用方式的信息和讨论; 我想指出解决方案必须使用LIKE '%text%'(也就是说,我要查找的文本是前缀并附加了%通配符).数据库也必须是本地的,原因很多,包括安全性.

rek*_*o_t 64

索引不会加速查询,因为对于文本列索引通过从左开始索引N个字符来工作.当您执行LIKE'%text%'时,它无法使用索引,因为在文本之前可能存在可变数量的字符.

你应该做的不是使用这样的查询.相反,你应该使用MySQL支持MyISAM表的FTS(全文搜索).对于非MyISAM表自己制作这样的索引系统也很容易,你只需要一个单独的索引表,你可以在实际的表中存储单词及其相关的ID.

  • 我应该补充一点,自MySQL 5.6以来,InnoDB也可以使用全文搜索. (8认同)

Mic*_*ael 21

索引不会帮助文本与前导通配符匹配,索引可用于:

LIKE 'text%'
Run Code Online (Sandbox Code Playgroud)

但我猜这不会削减它.对于这种类型的查询,如果要扩展可以搜索的记录数量,则应该查看全文搜索提供程序.我的首选供应商是Sphinx,非常全功能/快速等.Lucene也值得一看.MyISAM表上的全文索引也可以使用,但最终为任何具有大量写入的数据库追求MyISAM并不是一个好主意.

  • 在 MySQL 5.6 及更高版本中,它们还可以与 InnoDB 表一起使用。https://dev.mysql.com/doc/refman/5.7/en/fulltext-restrictions.html (2认同)

Jos*_*ter 14

添加全文索引并使用MATCH() AGAINST().

普通索引不会帮助您进行like查询,尤其是那些在搜索词两侧使用通配符的查询。

您可以做的是在您有兴趣搜索的列上添加全文索引,然后使用MATCH() AGAINST()查询来搜索这些全文索引。

  1. 在您需要的列上添加全文索引:

    ALTER TABLE table ADD FULLTEXT INDEX index_table_on_x_y_z (x, y, z);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后查询这些列:

    SELECT * FROM table WHERE MATCH(x,y,z) AGAINST("text")
    
    Run Code Online (Sandbox Code Playgroud)

从我们的试验中,我们发现这些查询在包含超过 100 万条记录的表中花费大约 1 毫秒。不错,尤其是与LIKE %text%需要 16,400 毫秒的等效通配符查询相比。

基准

MATCH(x,y,z) AGAINST("text") 需要 1ms

LIKE %text% 需要 16400 毫秒

快 16400 倍!

  • @JoshuaPinter 它不会找到包含“我正在发短信”字符串的行。所以不,全文和通配符不一样 (5认同)
  • 您没有提到 MATCH、AGAINST 与通配符不同!它就像一个where“=”,性能更高。 (2认同)

Mit*_*eat 13

索引不能用于加速搜索条件以通配符开头的查询:

LIKE '%text%'

索引可以(并且可能取决于选择性)用于表单的搜索项:

LIKE 'text%'


Ode*_*Wat 10

我想补充一点,在某些情况下,如果您正在查看的字段通常为空或包含某些常量,则可以使用索引和like/rlike来加速查询.

在这种情况下,您似乎可以通过添加带有固定值的"and"子句来限制使用索引访问的行.

我试着在一个巨大的表中搜索"标签",这个表通常不包含很多标签.

SELECT * FROM objects WHERE tags RLIKE("((^|,)tag(,|$))" AND tags!=''

如果您有标记索引,您将看到它用于限制正在搜索的行.


lin*_*eng 6

也许你可以尝试将mysql5.1升级到mysql5.7.

我有大约70,000条记录.并运行以下SQL:

select * from comics where name like '%test%'; 
Run Code Online (Sandbox Code Playgroud)

mysql5.1中需要2000ms.在mysql5.7或mysql5.6中需要200ms.

  • 这真的闻起来好像并非所有数据都缓存在5.1上的buffer_pool中.10:1是典型因素.此区域内没有任何内容从5.1变为5.6. (3认同)