- ベストアンサー
バッチ処理でレコード数が多いテーブルの結合について
- 300~500万件程度のテーブルを結合する方法について考えています。両者は1:1ではなく、ない場合も正常な構成です。また、最新のレコードを取得する必要があります。
- パフォーマンス問題を解決する方法として、SQLでのjoinを避ける方法や、javaの処理でループして結合する方法があります。
- どのような方法がより効率的でパフォーマンスのリスクを抑えられるか、アドバイスをお願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
#2です。 例のようにあった場合に「テーブルA」を主にして処理することを考えていました。 テーブルAからキーを抽出し、テーブルBから先のキーから必要データを抽出すると言うものです。 このとき、=条件(一本釣りと読んでいました)で読み出すようにすればDBMSに負荷がかかりません。 aixでDB2であれば問題ないような気もしますが。 ※取引日と取引時刻が分かれているのはやりにくいですね。 考えていたのは以下のようなものです。 (1) select 取引ID from テーブルA group by 取引ID order by 取引ID; で取引IDを抽出する。 (2) while 取引IDがある間 select 取引日,取引時刻,口座ID,通貨ID from テーブルA where 取引ID=@取引ID@ order by concat(取引日,取引時刻) desc; で最新の日付を取得する。 (3) while 取引IDがある間 select ..... from テーブルB where 口座ID=@口座ID@ and .. and 取引時刻=@取引時刻@ ... どのような情報を欲しておられるのか分かりませんが、 ・キーが適切に設定されていればそのままSQLを投げればよいと思います。 ・そうでなければ上記の取引日,取引時刻,口座ID,通貨IDを適切にsortすればテーブルBのレコードを一本釣りできると思います。 上記はキーが適切ではない場合の参考例と思ってください。
その他の回答 (2)
- いけだ ひろし(@ike-2000)
- ベストアンサー率53% (69/129)
#1です。 テーブルAとテーブルBがあり、それぞれに共通のkey1、key2があると考えます。 テーブル包含関係になっているものと考えています(考察は含む側で考えています)。 RDBMSが分からないので極力その機能を使わない方式です。 (1)履歴を無視したキーを抽出します。 これは、キー数が多い方でやります。 (2)履歴を無視したキーで検索し有効なレコードキーを所得します。 select key1,key2 from x where key1=@1 order by dec key2 といった感じです(必要なのは先頭の一件だけ)。 これで一意に決定できるキー(例ではkey1,key2)を求めます。 (3)key1,key2を使って=条件で一件ずつテーブルデータを読みます。 (両テーブルについてJOINしないでそれぞれ抽出します)。 key1,key2にはインデックスが設定してあることが望ましいです。 また、私はkey1,key2を登場させましたがもっと多くの条件があるかもしれません。 適宜置き換えてください。 保存する場所はファイルでもメモリでもかまいません。メモリが大きくあればメモリが良いでしょう。見極めはお願いします。 考えたのはDBMSのパフォーマンスに余り左右されない方法で、行う仕事を細かく分業化し処理を単純化したもので。 これらの制御の部分をJavaで書きます。DBMSのチューニングはDBMSに依存しますがこの方法なら汎用的です。DBのチューニングは一部ですみます。 ある程度想定して方式案を出してみました。2つのテーブルの関係がどうなっているのかが一番分からないところですがあるキーで包含関係になると言う条件でやっています。 条件の詳細が分かればもう少し的外れでない案を出せるかもしれません。
お礼
お返事ありがとうございます。情報不足 & 飲み込みが悪くて申し訳ありません。 環境は下記になります。 os:aix DB:DB2 9.7 java:jdk5 テーブルA 取引ID(PK) 取引日(PK) 取引時刻(PK) 口座ID 通貨ID 取引金額 ※その他割愛 レコード例) 1, 20100705, 0100, a, jpn, 1000 1, 20100705, 0200, a, jpn, 2000 1, 20100705, 0300, a, jpn, 3000 2, 20100705, 0400, a, jpn, 3000 3, 20100705, 0100, b, jpn, 3000 4, 20100705, 0100, c, jpn, 3000 テーブルB 口座ID(PK) 通貨ID(PK) 取引日(PK) 取引時刻(PK) 残高 ※その他割愛 レコード例) a, jpn, 20100705, 0100, 11000 a, jpn, 20100705, 0200, 12000 a, jpn, 20100705, 0300, 13000 a, jpn, 20100705, 0400, 16000 b, jpn, 20100705, 0100, 3000 c, jpn, 20100705, 0100, 3000 d, jpn, 20100704, 0100, 100000 e, usd, 20100703, 0100, 100000 ※上記では取引日と時刻は両テーブルで一致していますが、実際は一致するとは限りません。 最新のレコードはテーブルAは取引ID単位で取引日、取引時刻がもっとも未来のレコード、 テーブルBは口座IDと通貨ID単位で取引日、取引時刻がもっとも未来のレコードとなります。 このような場合、下記のようなことでしょうか? (1)履歴を無視したキーを抽出します。 →キーが多いというのはキーの種類でしょうか。レコード数でしょうか。 (2)履歴を無視したキーで検索し有効なレコードキーを所得します。 →(1)で取得したキーに対して上記のsqlを1つずつ発行するのでしょうか。 また「order by dec key2」はkey2が一番大きいものをkey1に対する最新レコードという想定でしょうか。 申し訳ありません。このあたりでよく分からなくなってきました。
- いけだ ひろし(@ike-2000)
- ベストアンサー率53% (69/129)
条件が良く分からないので、非力なマシン、DBMSということで。 (1)キー抽出(GROUP BY)しワークファイル1に書き出し。 (もしGROUP BYもきついならとにかくキーをワークファイル0に吐き出しsortする(ワークファイル1)。) (2)ワークファイル1を使ってユニークキー抽出(履歴考慮)しワークファイル2に書き出し。 (3)ワークファイル2を使って両テーブルデータ抽出。 とすれば極端なボトルネックは発生しないでしょう。 後はマシンパワーです。 この方法なら遅くなるにしてもどれだけの時間が必要か計算できると思います。
お礼
お返事有難うございます。 申し訳ありません。よく分からない部分があり、質問させてください。 (1)キー抽出(GROUP BY)しワークファイル1に書き出し。 →履歴を除いた最新のレコードをファイル1に書き出すという認識でよいでしょうか? また2つテーブルがありますが、どちらもファイル1に書き込むということでしょうか? (2)ワークファイル1を使ってユニークキー抽出(履歴考慮)しワークファイル2に書き出し。 →(1)で履歴を除いた最新のレコードがある認識ですが、履歴考慮の部分とユニークキーの部分が少し分かりませんでした。 (3)ワークファイル2を使って両テーブルデータ抽出。 →2つのテーブルからデータをファイルに書き出してjavaで結合してデータを取得するのかと思ったのですが、テーブルを見なおすのでしょうか? 申し訳ありません。よろしかったら教えて頂けると助かります。
お礼
お返事有難うございます。 連絡が遅くなり申し訳ありません。上記のご説明でよく分かりました。 この方法で検討してみたいと思います。 またこの関連の件で質問をする可能性が高いのですが、もしお目に留まりましたらアドバイス頂ければと思います。 有難うございました。