web-dev-qa-db-ja.com

SELECTサブクエリdb2 9.5を使用したINSERT INTO

実行に4秒かかる次のクエリがあります。

SELECT TX.* FROM TABLE_X TX
  INNER JOIN TABLE_Y TY
    ON TY.VALUE_ID = VALUE_ID_IN
      AND TY.PROD_ID = TX.PROD_ID
WHERE (TX.PLACE_ID1 = VAR_PLACE_ID OR TX.PLACE_ID2 = PLACE_ID)
  AND (TX.DATE > TY.FIRST_DATE)
  AND (TX.TYPE_ID != VAR_TYPE_ID1_IN AND TX.TYPE_ID != VAR_TYPE_ID2_IN)
  AND (TX.COL1 != COL1_IN OR TX.COL2 != COL2_IN)

しかし、それをTEMPORARY TABLEに保存したい。次のクエリを実行すると、50秒かかります。

INSERT INTO SESSION.TEMP_TABLE_X   /*new line to store result*/
    SELECT TX.* FROM TABLE_X TX
      INNER JOIN TABLE_Y TY
        ON TY.VALUE_ID = VALUE_ID_IN
          AND TY.PROD_ID = TX.PROD_ID
    WHERE (TX.PLACE_ID1 = VAR_PLACE_ID OR TX.PLACE_ID2 = PLACE_ID)
      AND (TX.DATE > TY.FIRST_DATE)
      AND (TX.TYPE_ID != VAR_TYPE_ID1_IN AND TX.TYPE_ID != VAR_TYPE_ID2_IN)
      AND (TX.COL1 != COL1_IN OR TX.COL2 != COL2_IN)

TABLE_X = 300 000行

TABLE_Y = 90 000行

どうすれば50秒の実行時間を短縮できますか?

サーバーはDB2 v9.5を実行しています。

1
Logar314159

コメントしやすいので、これを答えとして取り上げます。

一般に、すべてのテーブルでRUNSTATSを実行する必要があります(少なくとも週に1回は投票します)。これにより、オプティマイザにレコードの数(および指定されている場合は、私がお勧めします)のレコード間のデータの分布がわかります。この情報を使用して、オプティマイザはアクセスパスに関してより適切な決定を行うことができます。

オプティマイザもパッケージを使用します。パッケージをREBINDINGすると、基本的に、見つかったRUNSTATSに基づいてパッケージ(つまり、それらのアクセスパス)が変更されます。

あなたの場合、気になるテーブルでRUNSTATSを実行できます

RUNSTATS ON TABLE <schema>.<table> WITH DISTRIBUTION AND DETAILED INDEXES ALL

テーブルがたくさんある場合は、動的にハンティングすることをお勧めします

--do note syntax is for Unix, having to worry about escape characters and what not.
db2 -tnx  "select 'runstats on table ' || 
ltrim(rtrim(tabschema))||'.'||ltrim(rtrim(tabname))
|| ' with distribution and detailed indexes all ;'
from syscat.tables where type = 'T' and ownertype = 'U' and 
tabschema not in ('SYSCAT','SYSIBM','SYSIBMADM','SYSPUBLIC','SYSSTAT','SYSTOOLS') 
order by tabschema asc" >> runstats.sql

これをデータベースに読み込んで実行できます

db2 -tvf runstats.sql

REBINDs db2rbindユーティリティを使用するのが最も簡単です。特定のパッケージ名をすべて知っている必要はありません。私たちは小さなお店なので、毎回次の構文を使用する傾向があります。

db2rbind <my db> -l rebind.log all -r any

エラーがある場合は、ログに表示されます。

したがって、通常は最初にRUNSTATSを発行し、次にCOMMITを発行してロックを解放する必要があります。次に、REBINDs〜db2rbindを実行できます。しばらくこれらを実行していない場合は、RUNSTATSdb2 flush package cache dynamicの間にdb2rbindを入れることをお勧めします。

1
Chris Aldrich

一時テーブルには常にこの問題があります。 CPUリソースを大量に消費します。説明を行うと、アクセスタイプ「R」またはテーブルスキャンが表示されます。私はそうは思いません、あなたはそれをもっと良くすることができるでしょう。幸運を!

0
Ram27