2016-01-13 3 views
0

Я написал поисковый запрос, который ищет похожие имена. Он работает с Power Set тегов и сортирует по сходство. например, если текст поиска: shakespeare tragedy hamletКак оптимизировать поисковый запрос SQL?

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. если первый союз возвращает 10 строк, другие бесполезны.

Есть ли способ оптимизировать этот запрос?

+0

Где код, который генерирует этот sql? И вы ищете только строку, которая будет содержать все теги? или 1 из них достаточно, как последние 3 строки вашего запроса. – sagi

+0

@sagi Я считаю, что все знают, как работает poweret, поэтому я не прошел код генерации. Я ищу похожие строки, отсортированные по сходству. –

ответ

0

Мы можем получить все boosk, где имя похоже на прошлый тег, и добавить пользовательский 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 

UPDATE: ORDER BY может быть основана на сумме или просто запятые

+0

заказать по убыванию, конечно. –

+0

Да, по убыванию. Извините, забыл упомянуть – StanislavL

+0

, пожалуйста, отредактируйте ваш код –

0

При переключении на FULLTEXT индекс и использовать

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

вы можете получить несколько разумный порядок, и запустить много быстрее.

Если вы хотите настоять на shakespeare, находящемся в строчке, но остальные не являются обязательными, это работает лучше: '+shakespeare tragedy hamlet'.

Предостережение. Имеются как преимущества, так и ограничения FULLTEXT.

Смежные вопросы