我想实现一个书店的搜索查询。我使用 MySQL,我有一个 varchar 列,其中包含姓名、作者或其他详细信息,例如威廉·莎士比亚的《丹麦王子哈姆雷特的悲剧》,我想像莎士比亚悲剧一样进行搜索code> 或 丹麦悲剧
列出书籍列表,将它们放在一列中。
我有三个查询来实现此目的,但我想了解它们的性能。
喜欢%%
我的第一种方法是将搜索文本拆分为单词并根据字数创建动态命令:
SELECT * FROM books
WHERE name LIKE '%shakespeare%'
AND name LIKE '%tragedy%'
但我被告知 like
是一个慢操作符,特别是两个 %,因为它不能使用索引。
TAG表和关系划分
我的第二种方法是使用另一个包含以下标签的表:
-------------------------
| book_id | tag |
|-----------------------|
| 1 | Tragedy |
| 1 | Hamlet |
| 1 | Prince |
| 1 | Denmark |
| 1 | William |
| 1 | Shakespeare |
-------------------------
并创建动态除法命令:
SELECT DISTINCT book_id FROM booktag AS b1
WHERE ((SELECT 'shakespeare' as tag UNION SELECT 'tragedy' as tag)
EXCEPT
SELECT tag FROM booktag AS b2 WHERE b1.book_id = b2.book_id) IS NULL
但有人告诉我关系除法
也太慢了。
正则表达式
我的第三种方法是使用正则表达式:
SELECT * FROM books
WHERE name REGEXP '(?=.*shakespeare)(?=.*tragedy)'
但是有人告诉我它比LIKE
慢
请帮我决定哪种方式更快?
最佳答案
当然,使用内置操作数LIKE
比正则表达式更优化。但这里有一个重要的点,您不能将这两个方法放在一起比较,因为 LIKE
用于向字符串添加通配符,而正则表达式用于基于可能非常复杂的模式匹配字符串。
无论如何,我想到的实现这一目标的最佳方法是以下之一:
- 对已正确索引的列使用
LIKE
。1 - 使用一些优化的搜索技术,例如 elastic search .
- 实现多线程算法2,该算法在 IO 任务中表现非常出色。对于这个,您可以使用一些技巧,例如定义偏移量并在线程之间划分表。
另外,对于一些替代方法,请阅读这篇文章 https://technet.microsoft.com/en-us/library/aa175787%28v=sql.80%29.aspx
<子> 1. 您应该小心在列上放置索引的方式。阅读此答案以获取更多信息 https://stackoverflow.com/a/10354292/2867928和这篇文章http://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
<子> 2.阅读此答案以获取更多信息Multi Thread in SQL?
关于regex - 在 MySQL 中搜索 varchar 列的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34507478/