3つの課題があります。
クエリにはテーブルとの間のJOIN
条件がないため、これは事実上制限されます。これはおそらく意図しないことです。つまり、対象となるすべての電話は、対象となるすべてのグループと組み合わされます。100台の電話と100のグループがあり、すでに10,000の組み合わせになっている場合。phones
groups
CROSS JOIN
の異なる組み合わせを挿入します(group_id, phone_name)
テーブルにすでに存在する行を挿入しないでくださいgroup_phones
。
それが次のように見えると考えられるすべてのもの:
INSERT INTO group_phones(group_id, phone_name)
SELECT i.id, i.name
FROM (
SELECT DISTINCT g.id, p.name -- get distinct combinations
FROM phones p
JOIN groups g ON ??how are p & g connected??
WHERE g.id IN ($add_groups)
AND p.name IN ($phones)
) i
LEFT JOIN group_phones gp ON (gp.group_id, gp.phone_name) = (i.id, i.name)
WHERE gp.group_id IS NULL -- avoid duping existing rows
並行性
この形式は、同時書き込み操作による競合状態の可能性を最小限に抑えます。テーブル の同時書き込み負荷が大きい場合は、テーブルを排他的にロックするか、シリアル化可能なトランザクション分離を使用することをお勧めします。これにより、制約検証(行ありません)およびクエリの書き込み操作。
BEGIN ISOLATION LEVEL SERIALIZABLE;
INSERT ...
COMMIT;
シリアル化エラーでロールバックした場合は、トランザクションを繰り返す準備をしてください。このトピックの詳細については、@depeszによるこのブログ投稿またはSOに関するこの関連質問が出発点として適しています。
ただし、通常は、これを気にする必要はありません。
パフォーマンス
LEFT JOIN tbl ON right_col = left_col WHERE right_col IS NULL
一般に、右側のテーブルに個別の列がある最速の方法です。列に重複がある場合(特に多数ある場合)、
WHERE NOT EXISTS (SELECT 1 FROM tbl WHERE right_col = left_col)
最初の行が見つかるとすぐにスキャンを停止できるため、高速になる可能性があります。
IN
@dezsoが示すように、を使用することもできますが、PostgreSQLでは通常低速です。