2015-05-20 3 views
5

на postgresl 9.0 мы имеем SQL-запрос:Запрос не будет PostgreSQL закончить

SELECT count(*) FROM lane 
WHERE not exists 
    (SELECT 1 FROM id_map 
    WHERE id_map.new_id=lane.lane_id 
    and id_map.column_name='lane_id' 
    and id_map.table_name='lane') 
and lane.lane_id is not null; 

, что обычно занимает несколько около 1,5 секунд, чтобы закончить. Вот план объяснений: http://explain.depesz.com/s/axNN

Иногда этот запрос зависает и не заканчивается. Он может работать даже 11 часов без успеха. Затем он занимает 100% от процессора.

Единственными замками, которые этот запрос является, являются «AccessShareLock», и все они предоставляются.

SELECT a.datname, 
     c.relname, 
     l.transactionid, 
     l.mode, 
     l.granted, 
     a.usename, 
     a.current_query, 
     a.query_start, 
     age(now(), a.query_start) AS "age", 
     a.procpid 
    FROM pg_stat_activity a 
    JOIN pg_locks   l ON l.pid = a.procpid 
    JOIN pg_class   c ON c.oid = l.relation 
    ORDER BY a.query_start; 

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

SELECT count(*) FROM {} WHERE not exists (SELECT 1 FROM id_map WHERE id_map.new_id={}.{} and id_map.column_name='{}' and id_map.table_name='{}') and {}.{} is not null 

Обновления или удаления происходят параллельно этому процессу, поэтому я не думаю, что пылесосом может быть проблема здесь. Перед запуском всего процесса (поэтому до запуска 6 запросов такого типа) был проведен анализ всех таблиц.

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

Любая идея, что может вызвать такое поведение и как предотвратить его?

объяснить план без анализа:

Aggregate (cost=874337.91..874337.92 rows=1 width=0) 
    -> Nested Loop Anti Join (cost=0.00..870424.70 rows=1565283 width=0) 
     Join Filter: (id_map.new_id = lane.lane_id) 
     -> Seq Scan on lane (cost=0.00..30281.84 rows=1565284 width=8) 
       Filter: (lane_id IS NOT NULL) 
     -> Materialize (cost=0.00..816663.60 rows=1 width=8) 
       -> Seq Scan on id_map (cost=0.00..816663.60 rows=1 width=8) 
        Filter: (((column_name)::text = 'lane_id'::text) AND ((table_name)::text = 'lane'::text)) 
+0

я имел такое же проблему с Java , Это была не версия postgres - это было java, не прекращающее соединение ... 100% -ный процессор по postgres или java? .. что находится в pg_stat_activity? .. –

+0

100% от postgres. pg_stat_activity показывает бесконечный sql-запрос – norbitheeviljester

+0

, когда он переходит на 100% -ный процессор, вы можете проверить план? .. Это могут быть вложенные циклы вместо хеш-соединений, что означает, что вы отдаете слишком мало ОЗУ для кеширования ... Другой подход - как свежие статистические данные «Но оба стоит изучать, если план выполнения отличается, когда он достигает 100% -ного CPU –

ответ

5
VACUUM ANALYZE VERBOSE; 

освежающей статистика должна помочь дб выбрать оптимальный план - не вложенные циклы, которые я считаю, взять 100% CPU

+0

Мне удалось убедиться, что это действительно стало основной причиной проблемы. Вложенный цикл создает 1,5 миллиона сканирований последовательностей таблицы id_map, для чего требуется несколько дней. При выполнении анализа вакуума на обеих таблицах перед запуском запроса запрос заканчивается менее чем за 2 секунды. – norbitheeviljester