如何优化搜索 SQL 查询?

How to optimize the search SQL query?

我写了一个搜索相似名字的搜索查询。它与标签的 幂集 一起工作,并按 相似性 排序。例如,如果搜索文本是:shakespeare tragedy hamlet

生成的SQL是:

SELECT DISTINCT id FROM (
    (SELECT * FROM books 
      WHERE name LIKE '%shakespeare%' 
      AND name LIKE '%tragedy%' 
      AND name LIKE '%hamlet%' limit 10)
    UNION
    (SELECT * FROM books 
      WHERE name LIKE '%shakespeare%' 
      AND name LIKE '%tragedy%' limit 10)
    UNION
    (SELECT * FROM books 
      WHERE name LIKE '%shakespeare%'  
      AND name LIKE '%hamlet%' limit 10)
    UNION
    (SELECT * FROM books 
      WHERE name LIKE '%tragedy%' 
      AND name LIKE '%hamlet%' limit 10)
    UNION
    (SELECT * FROM books WHERE name LIKE '%shakespeare%' limit 10)
    UNION
    (SELECT * FROM books WHERE name LIKE '%tragedy%' limit 10)
    UNION
    (SELECT * FROM books WHERE name LIKE '%hamlet%' limit 10)
) limit 10

有两个问题:

  1. 幂集在我的查询中创建了 2^tags - 1 个并集,这意味着如果有人想要精确并使用 6 个标签,它将是 63 个并集,这会使我的查询速度变慢.

  2. 如果第一个union returns10行,其他的都没用

有没有办法优化这个查询?

我们可以获取所有名称与过去的标签相似的书,并根据相似性添加自定义的ORDER BY。如果名称包含标签 +1 如果不是 0。如果名称包含所有 3 个标签,则总和为 3 如果只有一个总和为 1。

SELECT DISTINCT id 
FROM books 
where name LIKE '%shakespeare%'
   OR name LIKE '%tragedy%'
   OR name LIKE '%hamlet%'
ORDER BY IF(INSTR(name, 'shakespeare')>0,1,0)+
         IF(INSTR(name, 'tragedy')>0,1,0)+
         IF(INSTR(name, 'hamlet')>0,1,0) DESC
LIMIT 10

更新:ORDER BY 可以基于总和或逗号

如果切换到 FULLTEXT 索引并使用

MATCH(name) AGAINST('shakespeare tragedy hamlet')

您可以获得稍微合理的排序,并且 运行 更快很多

如果你想坚持 shakespeare 在字符串中,但其他的是可选的,这样效果更好:'+shakespeare tragedy hamlet'.

警告:FULLTEXT.

既有优点也有局限性