Параллельные запросы в Postgres - PullRequest
4 голосов
/ 07 марта 2011

Я постараюсь кратко описать, что я должен понять, цель этого вопроса. У меня есть большое многопоточное приложение, разработанное на Java. Каждый поток имеет жесткую логику для загрузки, проверки и анализа файла, а затем вставки этих данных в базу данных. Этап вставки / обновления базы данных тоже в потоке. Каждый поток выполняет несколько хранимых процедур, которые обновляют одну таблицу. Эти хранимые процедуры являются несколькими для каждого потока.

Эта база данных одновременно используется веб-приложением. Итак, как вы поняли, у меня проблема с тупиком. Я перепробовал все модели замков, но ни одна из них мне не помогла. В некоторые сроки SELECT from web работает долгое время.

Какой у меня вопрос в конце концов. Есть механизм / средства postgres для синхронизации хранимой процедуры или запроса? Я знаю, что это должно быть сделано с помощью модели замка, но у меня не было успеха. В качестве решения для MS Server я использую «WITH NOLOCK» для операторов SELECT. Я могу решить эту проблему с помощью синхронизации кода, но это действительно сложная логика.

По запросу выкладываю пример медленного запроса в процессе обновления.

SELECT c.id AS id,cn.name as name,c.parent_category_id AS parent_category_id,
        CASE WHEN EXISTS (
  SELECT p.id FROM category AS subcat
  INNER JOIN product AS p ON subcat.id = p.category_id
  WHERE subcat.parent_category_id=c.id LIMIT 1)
 THEN true ELSE false END AS autoupdate
        FROM category AS c
        INNER JOIN category_name AS cn ON c.id=cn.category_id
        LEFT JOIN category AS subcat ON subcat.parent_category_id = c.id
        WHERE c.parent_category_id=0AND cn.langid=1 AND c.id != 1
        AND EXISTS
            (SELECT p.id FROM product AS p
            WHERE p.category_id = c.id OR p.category_id = subcat.id LIMIT 1)
        GROUP BY c.sort,c.id,cn.name,c.parent_category_id
        ORDER BY c.sort, cn.name`

И объясните:

'Group  (cost=947.74..987.96 rows=15 width=40)'
'  ->  Sort  (cost=947.74..947.75 rows=15 width=40)'
'        Sort Key: c.sort, cn.name, c.id, c.parent_category_id'
'        ->  Merge Left Join  (cost=125.84..947.62 rows=15 width=40)'
'              Merge Cond: (c.id = subcat.parent_category_id)'
'              Filter: (SubPlan 2)'
'              ->  Sort  (cost=64.46..64.46 rows=3 width=40)'
'                    Sort Key: c.id'
'                    ->  Nested Loop  (cost=0.00..64.45 rows=3 width=40)'
'                          ->  Seq Scan on category c  (cost=0.00..41.69 rows=3 width=18)'
'                                Filter: ((id  1) AND (parent_category_id = 0))'
'                          ->  Index Scan using category_name_category_id_langid on category_name cn  (cost=0.00..7.56 rows=1 width=30)'
'                                Index Cond: ((cn.category_id = c.id) AND (cn.langid = 1))'
'              ->  Sort  (cost=61.38..62.46 rows=1084 width=16)'
'                    Sort Key: subcat.parent_category_id'
'                    ->  Seq Scan on category subcat  (cost=0.00..39.52 rows=1084 width=16)'
'              SubPlan 2'
'                ->  Limit  (cost=0.00..27.29 rows=1 width=8)'
'                      ->  Seq Scan on product p  (cost=0.00..36459.98 rows=1336 width=8)'
'                            Filter: ((category_id = $0) OR (category_id = $1))'
'  SubPlan 1'
'    ->  Limit  (cost=0.00..2.68 rows=1 width=8)'
'          ->  Nested Loop  (cost=0.00..17889.28 rows=6684 width=8)'
'                ->  Seq Scan on category subcat  (cost=0.00..40.60 rows=10 width=8)'
'                      Filter: (parent_category_id = $0)'
'                ->  Index Scan using product_category_id on product p  (cost=0.00..1764.16 rows=668 width=16)'
'                      Index Cond: (p.category_id = subcat.id)'

Спасибо! С наилучшими пожеланиями Артем

Ответы [ 2 ]

4 голосов
/ 07 марта 2011

Я думаю, что вы ищете термин " уровень изоляции ". Я предполагаю, что некоторые части вашего приложения могут допускать грязное чтение, неповторимое чтение или фантомное чтение. Но в текущих версиях PostgreSQL писатели не блокируют читателей, а читатели не блокируют писателей .

Итак, мой вопрос заключается в следующем: как вы узнаете, что задержка вызвана блокировкой, а не, скажем, дисковым вводом-выводом, загрузкой соединения, другими процессами (процессами, не связанными с dbms, такими как долго выполняющиеся cron работа), или что-то еще?

2 голосов
/ 07 марта 2011

Вам не нужно "WITH NOLOCK" в PostgreSQL, так как читатели никогда не будут блокироваться авторами.Единственный способ заблокировать SELECT для таблицы - это вручную заблокировать таблицу с монопольным доступом - это не то, что делается обычными операторами DML.Только ALTER TABLE получит такой замок.

Но я не уверен, что понял ваш вопрос.

У вас уже есть проблема с тупиками?Или вы думаете, они будут у вас без тестирования?

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