2013-06-08 2 views
1

У меня есть функция PostgreSQL, которая возвращает результат запроса в сетку результатов pgadmin ДЕЙСТВИТЕЛЬНО FAST. Внутри это простая функция, которая использует dblink для подключения к другой базе данных и делает возвращение запроса, так что я могу просто запуститьЗапрос PostgreSQL медленный при использовании NOT IN

SELECT * FROM get_customer_trans(); 

И это работает так же, как основной запрос таблицы.

Проблема заключается в том, что я использую пункт NOT IN. Поэтому я хочу запустить следующий запрос, но это необходимо навсегда:

SELECT * FROM get_customer_trans() 
WHERE user_email NOT IN 
    (SELECT do_not_email_address FROM do_not_email_tbl); 

Как я могу ускорить это? Что-нибудь быстрее, чем статья NOT IN для этого сценария?

ответ

9

get_customer_trans() не является таблицей - возможно, некоторая хранимая процедура, поэтому запрос не является тривиальным. Вам нужно взглянуть на то, что эта хранимая процедура действительно делает, чтобы понять, почему она может работать медленно.

Однако, независимо от хранимой процедуры поведения, добавив следующий индекс должен помочь много:

CREATE INDEX do_not_email_tbl_idx1 
    ON do_not_email_tbl(do_not_email_address); 

Этот индекс позволяет NOT IN запрос быстро вернуть ответ. Тем не менее, NOT IN, как известно, имеет проблемы с более старыми версиями PostgreSQL, поэтому убедитесь, что вы используете как минимум PostgreSQL 9.1 или новее.

ОБНОВЛЕНИЕ. Попробуйте изменить запрос:

SELECT t.* 
FROM get_customer_trans() AS t 
WHERE NOT EXISTS (
    SELECT 1 
    FROM do_not_email_tbl 
    WHERE do_not_email_address = t.user_email 
    LIMIT 1 
) 

Этот запрос не использует NOT IN и должны работать быстро. Я думаю, что в PostgreSQL 9.2 этот запрос должен работать так же быстро, как один с NOT IN.

+0

Ive уже есть индекс по этой колонке в do_not_email_tbl. И, как я уже упоминал, результат, возвращаемый функцией, очень быстрый. 'SELECT * from get_customer_trans()' быстро возвращает в сетку результатов запроса все 2,2 миллиона записей. Похоже, функция работает быстро. Я хочу еще больше фильтровать результат, получая только тех клиентов, которых нет в do_not_email_tbl. –

+0

ответ обновляется, чтобы избежать 'NOT IN' – mvp

+0

AWEESOMEEEE !!!. Спасибо! вы уверены, что логика правильная с выбором 1? Я не знаком с NOT EXISTS. –

0

Просто сделай это так:

SELECT * FROM get_customer_trans() as t1 left join do_not_email_tbl as t2 
on user_email = do_not_email_address 
where t2.do_not_email_address is null 
Смежные вопросы