2015-12-24 2 views
0

При выполнении следующего запроса иногда требуется 15 секунд, а иногда и 90 минут. Что вызывает эту большую разницу?SQL Query медленно с перерывами в postgres

INSERT INTO missing_products 
SELECT table_name, 
    product_id 
FROM products 
WHERE table_name = 'xxxxxxxxx' 
    AND product_id NOT IN (SELECT id 
           FROM new_products); 

Я попробовал объяснить на нем, и единственное, что я могу видеть это index only scan на новых продуктах. Я также переписал этот запрос вместо левого соединения и вставлял строки, где правая сторона NULL, но это вызывает ту же проблему со временем.

У меня есть следующие таблицы со структурой, что-то вроде следующего.

продукты

id bigint not null, 
product_id text not null, 
table_name text not null, 
primary key (id), 
unique index (product_id) 

new_products

id text not null, 
title text not null, 
primary key, btree (id) 

missing_products

table_name text not null, 
product_id text not null, 
primary key (table_name, product_id) 

Объяснить - Это имеет дополнительное поле в выражении WHERE, но должно дать хорошее представление. Время заняло 22 секунды.

Insert on missing_products (cost=5184.80..82764.35 rows=207206 width=38) (actual time=22466.525..22466.525 rows=0 loops=1) 
    -> Seq Scan on products (cost=5184.80..82764.35 rows=207206 width=38) (actual time=0.055..836.217 rows=411150 loops=1) 
     Filter: ((active > (-30)) AND (NOT (hashed SubPlan 1)) AND (feed = 'xxxxxxxx'::text)) 
     Rows Removed by Filter: 77436 
     SubPlan 1 
      -> Index Only Scan using new_products_pkey on new_products (cost=0.39..5184.74 rows=23 width=10) (actual time=0.027..0.027 rows=0 loops=1) 
       Heap Fetches: 0 
Planning time: 0.220 ms 
Execution time: 22466.596 ms 
+0

любезно предоставит вывод 'EXPLAIN ANALYZE', который поможет нам узнать, есть ли любые триггеры, которые могут вызывать медленность – Akash

+0

@Akash обязательно добавлено –

ответ

1

Видимо, глядя на выходе вашего EXPLAIN ANALYZE, то SELECT вряд ли принимает 800ms, большую часть времени , почти 22seconds Проводится в INSERTING строк.

Кроме того, кажется, что статистика не является точной для вашей таблицы new_products, так как она предсказывает 23 строки, тогда как фактические строки - только 0, жесткий план выглядит корректно сейчас, это может быть катастрофическим в зависимости от того, как таблица new_products используется на протяжении всей вашей приложение, я бы сначала ANALYZE стол за регулярные интервалы, если автоматический анализ не срабатывает, и следить за производительностью в течение нескольких дней.

+0

Хорошие наблюдения. Я думаю, было бы интересно увидеть фактические моменты, когда производительность плохая (90 минут), и посмотреть, пропорционально ли потрачено время в тех же местах или если оператор 'select' внезапно стал узким местом. – sstan

+0

Действительно, я подозреваю, что медленность 90 м будет связана с неправильной статистикой – Akash

+0

Если это проблема с неправильной статистикой, как исправить это, а не запускать ANALYZE через равные промежутки времени? –

0

Я хотел бы попробовать 2 вещи:

  1. Попробуйте добавить индекс на products.table_name, что вы, кажется, не имеют на данный момент.

  2. Попробуйте переписать запрос, чтобы использовать предложение not exists вместо not in. Иногда, база данных может выполнить запрос более эффективно, что путь:

Запрос с not exists:

INSERT INTO missing_products (table_name, product_id) 
SELECT p.table_name, p.product_id 
    FROM products p 
WHERE p.table_name = 'xxxxxxxxx' 
    AND NOT EXISTS (SELECT null 
        FROM new_products n 
        WHERE n.id = p.product_id) 
+0

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

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