2016-06-19 4 views
0

Следующий запрос в 10 раз быстрее, если я удалю предложение «ИЛИ».Медленный запрос SQL с использованием OR

WITH RECURSIVE toeng(lang1, english, syn, enid) AS 
(SELECT lang1.word, english.word, english.synonym, english.id 
FROM lang1 INNER JOIN english ON lang1.english_id=english.id 
UNION 
SELECT CAST('' as VARCHAR(255)), english.word, english.synonym, english.id 
FROM english JOIN toeng ON toeng.syn=english.id OR toeng.enid=english.synonym) 
.... 

Целью запроса является получение всех родителей/детей начального набора узлов рекурсивно. Есть ли способ сделать это быстрее? Я попытался разбить его на несколько соединений, но я не могу найти то, что полностью эквивалентно этому. Я использую PostgreSQL.

+0

У вас есть какие-либо индексы на 'english' или' toeng'? Если да, то какие столбцы? –

+0

'english' правильно проиндексирован,' id' является его основным ключом, а 'синоним' является внешним ключом к' id'. как для 'toeng', он определен рекурсивно, поэтому я не знаю, могу ли/как его индексировать. – splinter123

+1

Пожалуйста, прочтите http://stackoverflow.com/tags/postgresql-performance/info, затем отредактируйте свой вопрос и добавьте недостающую информацию. –

ответ

0

запрос в 10 раз быстрее, если удалить «ИЛИ» пункт

В этом случае, убедитесь, что у вас есть надлежащий индекс, созданный на toeng.enid (означает english.id) и english.synonym. Как правило, у вас должен быть индекс для столбцов, которые вы пытаетесь использовать в статье JOIN ON, WHERE, HAVING и ORDER BY.

0

Вы упомянули в своем комментарии, что индексируется english.id. Это хорошо.

Причина, по которой ваш запрос идет медленно, потому что FROM english JOIN toeng ON toeng.enid = english.synonym будет медленным. Без индекса на english.synonym предложение заставляет полностью сканировать таблицу.
Полная статья, toeng.syn = english.id OR toeng.enid = english.synonym может соответствовать несколько записей с помощью индекса english.id, но он по-прежнему требует полного сканирования таблицы, чтобы подобрать соответствующие english.synonym записи, не покрыты индексом. Оптимизатор знает, что нет смысла использовать индекс, если требуется полное сканирование таблицы, поэтому оно полностью пропускает индекс.

Решение: вам нужно будет добавить индекс english.synonym, либо в качестве отдельного индекса или как часть multi-column index (добавив его в индекс english.id).

+0

Спасибо. Я специально не создавал индекс на 'english.synonym', предполагая, что он был создан автоматически, так как это внешний ключ для' english.id'. Но я просто понял, что это не так в PostgreSQL (в то время как для MySql). Я попробую позже! – splinter123

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