久しぶりに本題のSQLServer です。
今まで知りませんでした。
MERGE文が使えるんですね。
SQL と言えば、言わずもがな「Select」「Insert」「Update」「Delete」の4文が基本です。
例えば、Table_A と、ほぼ同じ構造を持った Table_B があって、
必ずTable_Aが最新になっているとします。
最新になっているというのは、
1、レコードが増えている。
2、レコードが減っている。
3、レコードが更新されている。
とうことが考えられます。
この状態をTable_Bに反映させる。
例えば、夜間バッチでTable_Bを最新状態にする必要がある場合が想定されます。
今までなら、
Table_Bに不足しているレコードを特定して、Insert文を発行。
Table_Aには無いレコードを特定して、Delete文を発行。
Table_AにもTable_Bにもあるが、更新されているレコードに対して、Update文を発行。
と3回の比較処理を走らせる必要があるので、
大量のレコードの場合に、莫大なコストが必要になることがありました。
これを1回の比較で処理してしまうのが、Merge です。
まあ、言葉の意味のままのステートメントです。
私の場合、ORACLEにあるテーブルをそのままSQLServerに毎日夜間バッチでコピーしたいのですが、総レコード数は40万件以上あるのに、更新または追加されるのは、わずか1000件程度。
その1000件を最新に保つために、 Truncate で全消し、Insert で全書きをしていましたが、あまりにも非効率なのと、ディスクにも負担をかけると思います。
そこで考えたのが、リンクサーバーでORACLEに接続して、OpenQuery を発行します。
その際、更新年月日を参照して、前回処理日以降だけに絞る Where句を付けておきます。
OpenQuery なので、条件が入っても、ORACLE側で高速に処理されて返ってきます。
これで1000件程度のレコードが返ってくる。
これを一旦 Select Into ##tempTable で仮テーブルに保管して、SQLServer 側の本来保管したいテーブルと比較して、 MERGE 処理を行うことにしました。
毎日数分かかっていた処理が、数秒で完了するようになりました。
MERGE の構文自体は、他の方がたくさん例を挙げていただいているので、私は省略です。
でも、1行で書けるといっても、結構手間の必要な構文になります。
比較は1回ですが、マッチした場合の動作(通常は UpDate になるかな。)と、アンマッチの場合の動作を(私の場合は、Insert ですが、 場合によっては、 Delete になる。)それぞれ書かないとダメです。
まあ、当たり前と言えば当たり前ですけどね。
特に、 UpDate の場合は、カラムを全部書かないと(しかも、元と先の両方を書かないと)ダメなので、カラム数の多いテーブルだと、長ーい構文になっちゃいます。
0 件のコメント:
コメントを投稿