如何优化搜索SQL查询?

时间:2016-01-13 07:52:11

标签: mysql sql search optimization query-optimization

我写了一个搜索查询,搜索相似的名字。它适用于标签的 Power Set ,并按相似性进行排序。例如,如果搜索文本为: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. Power Set会在我的查询中创建2^tags - 1个联合,这意味着如果某个人想要精确并且使用6个标签,它将是63个联合并且它使我的查询慢得多。

  2. 如果第一个联合返回10行,则其他联合没用。

  3. 有没有办法优化此查询?

2 个答案:

答案 0 :(得分:0)

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

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可以基于总和或只是逗号

答案 1 :(得分:0)

如果切换到FULLTEXT索引并使用

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

您可以获得一个合理的订购,并更快地运行 lot

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

警告:FULLTEXT有两个好处和局限。

相关问题