我有这张桌子:
bussId | nameEn | keywords
500 name1 name2 keyword1 keyword2
如果用户搜索(keyword1或keyword2或name2或name1),我想返回bussId 5000。
所以我应该使用这个查询SELECT * FROM business WHERE nameEn LIKE '%searched_word%'
。
但根据Comparison of B-Tree and Hash Indexes&#34,此查询不使用index nameEn or keywords
;如果LIKE
的参数是常量字符串,则该索引也可用于LIKE比较不以通配符开头#34;。
我有这个解决方案,我想创建另一个表并插入所有单词:
bussId | word
500 name1
500 name2
500 keyword1
500 keyword2
然后我将使用此查询搜索bussId:
SELECT * WHERE word LIKE 'searched_word%'.
通过这种方式,我将确保MySQL将使用索引,并且它会更快,但是这个表将包含大约2000万行!
还有其他解决方案吗?
答案 0 :(得分:6)
您必须使用MyisAM或InnoDB从MySQL 5.6开始使用全文索引:
mysql> ALTER TABLE business ADD FULLTEXT(nameEn, keywords);
以下是您的要求:
mysql> SELECT * FROM business
-> WHERE MATCH (nameEn, keywords) AGAINST ('searched_word');
答案 1 :(得分:0)
您是否尝试过Instr()或Locate()函数?这是SO discussion将它们与Like进行比较,但可能比前面的%通配符更好。它仍然运行全表扫描,但不知道MySQL查询优化器如何使用字符串函数进行索引。
SELECT * FROM business WHERE Instr(nameEN, 'search_word') > 0
OR
SELECT * FROM business WHERE Locate(nameEN, 'search_word') > 0
此外,可能还有其他优化领域。查看business
表中是否有其他可能的索引,如果未使用所有列,则显式声明特定列而不是星号(*),并解析nameEN
和keywords
列通过空格使列保留一个值(可以转置),然后使用隐式连接WHERE
或显式连接JOIN
。这甚至可能是一个表设计问题,存在在单个字段中存储多个值的挑战。
答案 2 :(得分:0)
使用新版本的MySQL你不需要制作引擎“MyISAM”,InnoDB也支持FULLTEXT索引(我已经测试了这个5.6.15,支持表单版本> = 5.6.4)。 因此,如果您的服务器版本高于5.6.4,则只需将FULLTEXT索引添加到您的表中,并使用MATCH(...)AGAINST(...)进行选择,下面的示例
CREATE FULLTEXT INDEX idx ON business (nameEn);
SELECT * FROM business
WHERE match(nameEn)against('+searched_word' IN BOOLEAN MODE);
答案 3 :(得分:0)
在MySQL或SQL中使用以下语句,它将返回完美结果:
SELECT * FROM business WHERE (nameEn LIKE 'searched_word%' OR nameEn LIKE '%searched_word%') OR (keywords LIKE 'searched_word%' OR keywords LIKE '%searched_word%') AND bussID = 500;
这应该有用。
答案 4 :(得分:0)
2000万条记录非常多,带有varchar列的映射表将为每行分配最大允许字符数字+ 32位整数列。
如果您可以创建一个像(id int,crc int)这样的表并仅存储文本数据的crc32值,该怎么办?它区分大小写,因此您需要在填充数据时转换为大写/小写,并在比较时进行相同的转换。
我同意全文方法,但为了节省空间并利用索引的优势,您可以尝试下面的内容。
Create Temporary TABLE t (id INT, crc INT);
Insert Into t
Select 500, CRC32(UPPER('name1'))
Union Select 500, CRC32(UPPER('name2'))
Union Select 500, CRC32(UPPER('keyword1'))
Union Select 500, CRC32(UPPER('keyword2'));
Select * From t Where crc = CRC32(UPPER('keyword2');