如何优化搜索 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
有两个问题:
幂集在我的查询中创建了 2^tags - 1
个并集,这意味着如果有人想要精确并使用 6 个标签,它将是 63 个并集,这会使我的查询速度变慢.
如果第一个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
.
既有优点也有局限性
我写了一个搜索相似名字的搜索查询。它与标签的 幂集 一起工作,并按 相似性 排序。例如,如果搜索文本是: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
有两个问题:
幂集在我的查询中创建了
2^tags - 1
个并集,这意味着如果有人想要精确并使用 6 个标签,它将是 63 个并集,这会使我的查询速度变慢.如果第一个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
.