3

これはおそらく以前に尋ねられたことがありますが、「IN」のようなキーワードのグーグルはあまりうまく機能しません。

これは私の質問です:

UPDATE tblCustomer SET type = 2 
WHERE idcustomer                                
IN (SELECT fidcustomer1
    FROM tblorder                   
     UNION                      
    SELECT fidcustomer2
    FROM tblorder                   
   )                                

内訳:注文テーブルのいずれかの列に表示されるすべての顧客について、すべての顧客のタイプ(intのみ)を2に設定します。

私のテストデータでは、これらのテーブルのいずれにも数百行を超える行は含まれていませんが、クエリは何分間も実行され(UNIONがなくても、大きな違いはないようです)、明らかに内部クエリを再実行します顧客の行ごとに1回。明らかに、それを単一のSELECT DISTINCT(id)に書き直してから、数百の単一行の更新を行い、ODBCアクセスに使用する言語でロジックを実行できますが、これは単なるハックです。

どうすればこれを正しく書き直すことができますか?

補遺:更新したいテーブルには、行ごとに数MBの比較的大きなBYTEAブロブが多数含まれています。これらはストレージ外部または拡張に設定されていますが、それによってシーケンシャルスキャンが遅くなる可能性があるのではないかと思います。これだけでなく、すべての更新には長い時間がかかるようです。

4

2 に答える 2

5

より簡単なアプローチを提案します。

UPDATE tblCustomer c
SET    type = 2 
FROM   tblorder o
WHERE  c.idcustomer IN (o.fidcustomer1, o.fidcustomer2)
AND    c.type IS DISTINCT FROM 2  -- optional, to avoid empty updates

ただし、に重複がある場合はtblorder、あなたが持っていたものと同様のアプローチが賢明です。

UPDATE tblCustomer c
SET    type = 2 
FROM  (
    SELECT fidcustomer1 AS cust FROM tblorder
    UNION
    SELECT fidcustomer2 FROM tblorder
    ) o
WHERE  c.idcustomer = o.cust
AND    c.type IS DISTINCT FROM 2;

いずれにせよ、PostgreSQLでは、テーブルへの結合は式よりも定期的にパフォーマンスが向上しINます。

于 2012-11-14T11:16:13.270 に答える
4
-------------------------------
-- Use two EXISTS:
-------------------------------
UPDATE tblCustomer tc
SET type = 2
WHERE EXISTS (
    SELECT *
    FROM tblorder ex
    WHERE ex.fidcustomer1 = tc.idcustomer
    )
OR EXISTS (
    SELECT *
    FROM tblorder ex
    WHERE ex.fidcustomer2 = tc.idcustomer
    );

-------------------------------
-- or combine the two EXISTS::
-------------------------------
UPDATE tblCustomer tc
SET type = 2 
WHERE EXISTS (
    SELECT *
    FROM tblorder ex
    WHERE ex.fidcustomer1 = tc.idcustomer
    OR ex.fidcustomer2 = tc.idcustomer
    );

私の直感では、最初のバージョン(2つの別個の存在)の方がパフォーマンスが向上します。これは、存在の1つが生成されるとエグゼキュータが短絡Trueする可能性があるためです。これにより、UNIONコンストラクトに固有の重複の削除フェーズ(およびおそらくソート)が回避されます。

于 2012-11-14T11:43:00.180 に答える