Home
About UsTechnologyMusicCharactersEconomyForum

ふたりはプリキュア 『ありえない!?狂わされたプラン』

前提知識解説

 本技術資料に登場するキャラクターは、東堂いづみ『ふたりはプリキュア』(2004-)を元ネタとしている。この作品は伝統的な変身少女モノの系譜に連なるが、ポップでおしゃれな描画、一見したところとは異なる主人公ふたりのキャラ、意外と凝ったアクションシーン……などによりに大好評を博している。なぎさとほのかは中学二年生であるが、本技術資料ではなぜか二人がデータベースやOracleアーキテクチャに詳しいという設定にしている。
参考リンク:
 ABC ふたりはプリキュア

本編

ピーサード:
「プリキュアのやつら、いつも邪魔しやがって……こうなったらおまえたちが住む虹の園(人間界)をメチャクチャにしてやる。ゆけ、ザケンナーよ! 人間どもの生活を支えているシステムに憑依するのだ!」

ザケンナー:
「ザケンナー!」

ピーサード:
「フハハハ……これでやつらの社会インフラはたちまちマヒ状態だ……!」

雪城ほのか:
「今夜の月次処理の調子はどうかしら……って大変! まだ第1ジョブネットも終わってないじゃない!」

ほのか:
「もしもし、美墨さん?」
美墨なぎさ:
「ふわぁ〜、あ、雪城さん? どうしたの? こんな夜中に……」
ほのか:
「ごめんなさい、でも大変なの! バッチが急に遅くなって、SQLプランがおかしくなっちゃってるの。」
なぎさ:
「プランがおかしいって、また開発者がタコなSQL書いたんじゃないの?」
ほのか:
「でも今月は新しいアプリも既存アプリの修正版もリリースされてないわ。先月と全く同じSQLソースなのにオプティマイザが全く別のプランを適用しているのよ。」
なぎさ:
「うーん、統計情報の問題かな? 最近急にデータが増えたテーブルとかない?」
ほのか:
「アナライズは『DBMS_STATS』を使って毎日かけているけど、データの量や分布に大きな変化は見られないわ……何か闇の力が働いている気がするの。ねえお願い、美墨さんも来て!」
なぎさ:
「う、うん、わかった、すぐ行くよ。」

ほのか:
「どう? 『V$SQL_PLAN』を見た?」
なぎさ:
「ええ、ほのかの言うとおりこれはたぶんドツクゾーンの連中のしわざね。ザケンナーがOracleの中に入ってオプティマイザを狂わせているんだわ。で、どうする?」
ほのか:
「コストベースオプティマイザが働かないように、ソースのSQLにヒント句を埋め込んでプランを固定するわ。朝のオンライン開始に間に合わせるにはそれしか方法がないと思う。」
なぎさ:
「えっ…それって、雪城さんと私のふたりでやるの?」
ほのか:
「ええ、そうよ。」

なぎさ:
「ちょ、ちょっと待った! わたし、実際にパフォチューした経験とかないのに…ぶっつけ本番だなんて、そんなのありえなーい!」
よし美課長:
「ありえなくありません! いいですか、システムトラブルでお客様やユーザーに迷惑をかけないことが私たち情シスの勤めです。雪城さん、美墨さんもある程度は知識があるはずだから、彼女をサポートしてあげて。」
ほのか:
「課長……分かりました。ふたりで力を合わせてなんとか間に合わせます!」

ほのか:
「美墨さん、インデックス(索引)の使い方くらいは大丈夫よね。」
なぎさ:
「B-Treeとかビットマップとかいうやつでしょ。そこらへんは大丈夫かな。けど……」
ほのか:
「他のところ?」
なぎさ:
「うん、テーブルをジョイン(結合)させるアルゴリズムの理解がちょっとあやふやっぽいんだ。ハッシュ・ジョインとかネステッド・ループ・ジョインとか……」
ほのか:
「では、結合動作の仕組みについて、ひととおりおさらいしましょうか。」

ほのか:
「ではまず、ネステッド・ループ・ジョインからいきましょう。これは結合する片方のテーブルから1行読み込んで(図の@)、もう片方のテーブルの結合対象カラムを走査(スキャン)する(図のA)という動作を繰り返すという結合方法よ。」
なぎさ:
「図の例では『社員』テーブルと『事業部』テーブルを『事業部ID』で結合しているのね。まず『社員』テーブルの1行目をフェッチして、この人の『事業部ID』は『03』だから『事業部』テーブルの『事業部ID』を検索して『事業部ID1=03』である『事業部名=金融』の行と結合する。次に『社員』テーブルの2行目をフェッチして、この人の『事業部ID』は『01』だから『事業部』テーブルの『事業部ID』を検索して『事業部ID1=01』である『事業部名=製造』の行と結合する……、これってひょっとして『社員』テーブルの行の数だけ『事業部』テーブルを繰り返しフル・スキャン(全件検索)するってこと? なんかディスクI/Oが多すぎて遅そう〜。』
ほのか:
「うん、特に何もしなければそうなっちゃうけど……。そこで結合対象カラム(『事業部.事業部ID』)にインデックスを張ってフル・スキャンを回避するのよ。結合対象カラムのカーディナリティ(値のばらつき)が大きければインデックスが効果的に働いて、繰り返し処理のオーバーヘッドを十分カバーできるわ。」
なぎさ:
「ふーん、そういう理屈なんだ。それならいっそのこと『事業部』テーブルをメモリにキャッシュすれば超早くなるんじゃない? まあ、メモリに乗っかるほど小さければの話だけど。」
ほのか:
「そうよ。さすが美墨さん、理解が早いわね。」
なぎさ:
「で、ネステッド・ループ・ジョインを使うヒント句の構文は?」
ほのか:
「『USE_NL(テーブル名)』よ。例で言うと『事業部』テーブルの方を『テーブル名』に入れるわ。これを内部表といって、『社員』テーブルの方を外部表、または駆動表と呼ぶの。」

ほのか:
「次は、ソート・マージ・ジョイン。これは結合する2つのテーブルをそれぞれ結合対象カラムの値でソートして(図の@、A)、その結果セットを並び順にマッチングさせてゆく結合方法なの。」
なぎさ:
「これは比較的分かりやすいわね。ネステッド・ループ・ジョインのように1行ずつ結合させるのではなくて、『選手』テーブルと『賞品』テーブルの行を『ランク』で並び替えてから、一気に突き合わせるということね。」
ほのか:
「そう、ソートするから結合条件がイコール(=)の場合だけじゃなくて、不等号(<,>=)の場合にも有効なの。」
なぎさ:
「結合条件が不等号って、実際そんなのあるの?」
ほのか:
「そうねえ、例えば日付マスタと結合するときは、日付の範囲を『BETWEEN』で指定して結合条件にするときがあるわ。そんなときにソート・マージ・ジョインが役立つのよ。」
なぎさ:
「あぁ、なるほどね。分かったわ。それで、ヒント句はどう書けばいいの?」
ほのか:
「『USE_MERGE(テーブル名A テーブル名B)』よ。特に内部表と外部表の区別がないから、順序はどちらでも構わないわ。」

ほのか:
「最後はハッシュ・ジョイン。『商品』テーブルと『在庫』テーブルを『商品ID』で結合したいのだけど、ふたつのテーブルを直接結合するのではなくて、まず『商品』テーブルをもとにハッシュ・テーブルを作ってから、これと『在庫』テーブルを結合するというやり方よ。」
なぎさ:
「う〜ん、前にOracleのマニュアル読んだときにそのハッシュ・テーブルというのが全然意味わかんなかったのよね。」
ほのか:
「そうですね……ハッシュ・テーブルというのはOracleが一時的に作る索引のようなものと考えてください。インデックスの場合、元テーブルのROWIDの集合をインデックス・キーの値の範囲でグループ分けしますよね。ハッシュ・テーブルは、元テーブル(図の例では『商品』)の結合対象カラム(図の例では『商品ID』)と検索対象カラムの値の集合を、結合対象カラムのハッシュ値でグループ分けしたものなの。(図の@)」
なぎさ:
「ハッシュ値っていうのは?」
ほのか:
「ここでは例として、『商品ID』の下1桁ということにしています。各グループに属する行数がだいたい均等になるような関数が使われます。実は私も詳しくは知らなくって……」
なぎさ:
「ふーん、そうなんだ。でもまあ、索引と似たような構造ってことはわかったわ。じゃあ次に、『在庫』テーブルの行をハッシュ・テーブルの行と結合させるところ(図のA)はどうなっているの?」
ほのか:
「『在庫』テーブルから1行フェッチして、その『商品ID』のハッシュ値を求めるの。それからハッシュ・テーブルの同じハッシュ値のところ(これをハッシュ・チェインと呼ぶわ)を見に行って、今度はハッシュ関数をかける前の元の『商品ID』でマッチングをかけるというわけ。」
なぎさ:
「1つのハッシュ値に複数の『商品ID』が対応するから、結局は『商品ID』で結合しなきゃいけないわけね。これだとネステッド・ループ・ジョインと変わらないじゃない。むしろハッシュ・テーブルを作る手間がかかるから、かえって遅くならないの?」
ほのか:
「えーと、でも、ネステッド・ループ・ジョインの場合は全ての行を見に行かなきゃいけないけれど、ハッシュ・ジョインの場合は同じハッシュ値をもつグループの中だけ探せばよいから、その分早くなるわ。」
なぎさ:
「……なるほど、大きなテーブルどうしを結合するときには有効そうね。」

ほのか:
「そのとおり! もう、美墨さんひょっとして知っていたんじゃないの?」
なぎさ:
「そんなことないわよ。教えてくれて、どうもありがとう。分かりやすかったわ。さあ、いよいよ仕事に取り掛かりましょうか。」
ほのか:
「ええ、……と、ヒント句の構文を言うのを忘れていたわ。」
なぎさ:
「今までの流れだとどうせ『USE_HASH(テーブル名A テーブル名B)』でしょ?」
ほのか:
「……やっぱり知ってたでしょ?」

ほのか&なぎさ:
「デュアル・オーロラ・ウェイブ!」
メップル:
「なぎさ! 『プリキュア・マーベラス・チューニング』を使うメポ!」
なぎさ:
「えっ? プリキュア・マーベラ……なにそれ?」
ミップル:
「ひとつずつエディタでソースを書き直さなくても、心でイメージするだけでソースが書き換わるミポ! Oracle内部のPコードも合わせて変わるから、再コンパイルもいらないミポ!」
ほのか:
「そ、そんな便利な技があるなら早く言ってくれればいいのに!」
なぎさ:
「あ〜、もう、何て言えばいいの!?」
メップル:
「ブラック・クエリーにホワイト・クエリーだメポ!」

なぎさ:
「ブラック・クエリー!」
ほのか:
「ホワイト・クエリー!」
ほのか:
「プリキュアの、美しき魂が!」
なぎさ:
「崩れたプランを、立て直す!」
ほのか&なぎさ:
「プリキュア・マーベラス・チューニング!」

ほのか:
「美墨さん、JP1コンソールを見て!ジョブがいつものスピードで進みだしたわ。」
なぎさ:
「ホント! よかった〜、私たちのチューニングが効いたんだ!」
よし美課長:
「ふたりとも、よくがんばったわね。夜を徹しての作業、ご苦労様。」

ピーサード:
「なっ……! ヤツらにあのような技術があるとは……。だが来週こそはこの借りを倍にして返してやるからな、覚悟しておけ!」