mysql Concat vs OR
Posted
技术标签:
【中文标题】mysql Concat vs OR【英文标题】: 【发布时间】:2014-09-13 08:15:05 【问题描述】:我试图找到在多个列中搜索单词出现的最佳方法。当然,一个选项是在查询中添加多个OR
:
SELECT * FROM table WHERE column1 LIKE %term1% OR column2 LIKE %term1% OR......
但我虽然这使查询变得很长,尤其是当有多个术语时
在我的搜索中,我发现了 mysql 中的 CONCAT
function。这似乎允许我在连接列后进行一次搜索(对吗?):
SELECT * FROM table WHERE CONCAT(column1,column2,....) LIKE %term1% OR CONCAT(column 1,column2,...) LIKE %term2% ....
这具有更易于阅读和维护的优势
因为我还没有完全理解CONCAT
的完整用法我不知道或者这是一个正确的使用方式。我想知道实现此搜索的正确和最有效的方法是什么。 (注意:我还计划按照这个 *** 问题中所述对其进行排序:mysql SORT BY amount of unique word matches,可能在使用这种方法时会出现问题?)
编辑:
也许只解释我的最终愿望会更容易:在 php 中,我有一个单词数组。我希望从我的数据库中选择所有行,其中 1 个单词出现在多个 colmun 之一中,然后按相关性对它们进行排序(甚至为某些列添加额外的重要性)。 (请注意,只有几千(少于 5000)行要搜索)
【问题讨论】:
有趣。在任何一种情况下,查找匹配行都会很慢(因为由于 LIKE 中的前导通配符,它不会使用索引)。这可能意味着对长字符串执行单个like 可能会更快。不利的一面是,如果您搜索术语 ME if 还会找到 column1 以 M 结尾且 column2 以 E 开头的行 @Kickstart : 如果通配符被跳过怎么办? ME问题可以通过concat_ws解决,不是吗? 我会坚持第一个选项,但我没有什么可以支持我的观点,除非你可能会得到错误的结果。例如:第 1 列:Rapido,第 2 列:太好了,您最终会得到 RapidoGreat,并且您将匹配“狗”。 Concat_ws 修复它,直到用户碰巧搜索包含您选择使用的分隔符的字符串。前导通配符的问题是 MySQL 不能使用索引来查找它们(它可能可以使用尾随通配符)。如果没有前导通配符,则使用大量 OR 将允许使用索引,但将字段连接在一起将确保仍需要前导通配符。 帖子末尾的“按相关性排序”会立即导致“全文”作为解决方案。这就是它的意图。但是如果你不能使用它,因为你的 InnoDB 版本不支持它是的 - 那么,好的,最好的建议:将你的 MySQL 服务器升级到 5.6。否则,您将始终围绕着这种神秘的解决方案。从性能的角度来看OR LIKE
可能使用索引,但这不能保证,通常情况下不会。因此,双向方式很糟糕,唯一重要的可能是可读性。这是您的决定。
【参考方案1】:
最好的方法是使用全文搜索引擎来完成这项任务,或者使用 MySQL 的全文功能。
你可以在这里找到更多的解释: fulltext-natural-language
【讨论】:
但是使用INNOdb表并且不确定正在使用mysql 5.6,这个不能用 在这种情况下 - 使用外部全文搜索引擎。 我好像还没有听说过。你能解释一下吗? 您可以使用外部全文引擎,例如 Solr、Sphinx 或 Elasticsearch。然后,您应该使用一个键定义每 X 分钟从数据库中提取数据的查询。并在那里执行所有搜索,而不是在 mysql 中。【参考方案2】:因为我认为这是一个有趣的观点,所以我认为最好尝试一下。
好吧,在您编辑之后,您似乎没有那么多数据,但我还是会发布结果:
编辑:这是我第一次尝试 MySQL 测试,正如@Alma Do 所说,这些结果“可能只是波动”。
第一个查询(90000 行)road
和 road2
是 VARCHAR(100)
:
SELECT * FROM adress WHERE CONCAT(road1,road2) LIKE '%test%';
0.0503 秒
SELECT * FROM adress WHERE road1 LIKE '%test%' OR road2 LIKE '%test%';
0.0710 秒
看起来确实多个LIKE
更足智多谋。我对MySQL
资源验证不是很擅长,所以我没有继续深入,估计它仍然应该提供一个想法。
我看到的主要问题是CONCAT
是否会创建错误的匹配项:
SELECT CONCAT('fooa','bfoo')
和 LIKE '%ab%'
可以工作,而 'fooa' LIKE '%ab% OR 'bfoo' LIKE '%ab% OR
不能。
对于 500 行,我认为您不会遇到资源问题,所以我会选择“具有更易于阅读和维护的优势”。
希望对你有帮助
【讨论】:
这些测量值只是几乎毫无意义的数字。实际情况可能取决于许多情况。例如,第一列可能总是包含所需的单词,因此,第二个LIKE
将永远不会被执行(短路)。或者,否则,如果第一列不包含该单词,则将为每一行执行两个LIKE
。唯一合适的点是 - 单词重叠边缘情况,但这可以通过使用分隔符来修复。但是,90.000 也太小了,无法在测试结果中认真看待。 0.01..0.05 秒可能只是波动。
感谢提示,这实际上是我第一次尝试做一些 MySQL 测试,想看看我是否可以做点什么,但事实上,很多细节开始成为问题.. . 我相信他们可能确实没有那么精确,但是,希望它仍然可以帮助:)
对我来说已经足够了?
为“更易于阅读和维护”点赞!
顺便问一下:看看能不能用CONCAT_WS代替CONCAT。以上是关于mysql Concat vs OR的主要内容,如果未能解决你的问题,请参考以下文章
Pandas DataFrame concat vs append
Java:String concat vs StringBuilder - 优化了,我该怎么办?