スキャンされるセット全体の行ごとに1回pg_try_advisory_lock()を呼び出しています(where
で発生するフィルタリングの一部として) 句)、クエリによって返されるtable1の行ごとに1回だけ呼び出されるようにします。
代わりにサブクエリまたはCTEを使用してみてください:
with rows as (
SELECT a.id
FROM table1 a
JOIN table2 b ON a.table1_id = b.id
WHERE table2.id = 1
)
select rows.*
from rows
where pg_try_advisory_lock('table1'::regclass::integer, rows.id);
ただし、必ずしも期待どおりに機能することに依存しないでください。Postgresは、最初のクエリと同じように書き直したくなるはずです。
select
なので、もう1つの可能性はこれです。 ステートメントの一部は、クエリの非常に遅い段階で評価されます:
with rows as (
SELECT a.id,
pg_try_advisory_lock('table1'::regclass::integer, a.id) as locked
FROM table1 a
JOIN table2 b ON a.table1_id = b.id
WHERE table2.id = 1
)
select rows.id
from rows
where rows.locked;
実際の本当の問題は、pg_try_advisory_lock()
これは、あなたがしているようなクエリではなく、アプリランドや関数で通常見られるものです。そういえば、何をしているのかにもよりますが、select … for update
を使用すべきではないと確信しています。 ?
更新について:
はい。 limit 1
のため 、一致するものを見つけてすぐに停止します。ただし、おそらく起こっているのは、where
を評価していないということです。 クエリに応じて同じ順序で句。 SQLは、a <> 0
を保証するものではありません。 a <> 0 and b / a > c
の一部 最初に評価されます。あなたのケースに適用され、それはアドバイザリーロックが後に取得されるという保証を提供しません aの行はbと結合されます。