【问题标题】:How to search for a text? (MySQL)如何搜索文本? (MySQL)
【发布时间】:2015-06-24 02:03:37
【问题描述】:

我有这张桌子:

bussId    |      nameEn        |          keywords
  500          name1 name2             keyword1 keyword2

如果用户搜索(关键字 1 或关键字 2 或名称 2 或名称 1),我想返回 bussId 5000。 所以我应该使用这个查询SELECT * FROM business WHERE nameEn LIKE '%searched_word%'。 但是这个查询不使用index nameEn or keywords,根据Comparison of B-Tree and Hash Indexes“如果LIKE的参数是一个不以通配符开头的常量字符串,该索引也可以用于LIKE比较”。

我有这个解决方案,我想创建另一个表并插入所有单个单词:

bussId |  word
  500        name1
  500        name2
  500        keyword1
  500        keyword2

然后我将使用以下查询搜索 bussId:
SELECT * WHERE word LIKE 'searched_word%'.

这样我就可以肯定 MySQL 会使用索引,而且会更快,但是这个表会包含大约 2000 万行!

还有其他解决方案吗?

【问题讨论】:

  • SELECT * FROM business WHERE nameEn LIKE '%searched_word%' 这应该有效。我不明白它的问题。你能澄清一下吗?我在工作中一直在以相同的目的使用该查询
  • @LuigiMackenzieC.Brito 问题是查询很慢,因为它不使用索引,它搜索整个表!
  • Dang,它不会只搜索整个“命名”列吗?
  • 哇,我终于学到了新东西:)

标签: mysql sql search


【解决方案1】:

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');

【讨论】:

    【解决方案2】:

    在 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;  
    

    这应该可行。

    【讨论】:

      【解决方案3】:

      从 MySQL 5.6 开始,您必须使用 MyISAM 或 InnoDB 使用全文索引:

      mysql> ALTER TABLE business ADD FULLTEXT(nameEn, keywords);
      

      这是您的要求:

      mysql> SELECT * FROM business
         -> WHERE MATCH (nameEn, keywords) AGAINST ('searched_word');
      

      【讨论】:

      • 感谢您的回答。但不幸的是我不能使用 myisam 引擎。我可以只使用 InnoDb。因为我使用的是 aws rds。所以我无法使用 FULLTEXT 搜索。谢谢
      • InnoDB 从 MySQL 5.6 开始也支持全文搜索。
      • 我的错误。好消息!
      【解决方案4】:

      使用新版本的 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);
      

      【讨论】:

        【解决方案5】:

        您是否尝试过 Instr() 或 Locate() 函数?这是一个SO discussion 将它们与 Like 进行比较,但比较前面的 % 通配符可能会更好。它仍然运行全表扫描,但不知道 MySQL 查询优化器如何使用字符串函数进行索引。

        SELECT * FROM business WHERE Instr(nameEN, 'search_word') > 0 
        

        SELECT * FROM business WHERE Locate(nameEN, 'search_word') > 0 
        

        此外,可能还有其他优化领域。查看business 表中是否有其他潜在索引可用,如果未使用所有列,则显式声明特定列而不是星号 (*),并通过空格解析 nameENkeywords 列,以便保留列一个值(有可能转置),然后使用隐式连接 WHERE 或显式连接 JOIN。这甚至可能是一个表设计问题,难以在单个字段中存储多个值。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-08
          • 1970-01-01
          • 2019-09-08
          • 2015-08-14
          • 1970-01-01
          • 1970-01-01
          • 2012-06-25
          • 2012-04-06
          相关资源
          最近更新 更多