最初に
今日は、JPOUG Advent Calendarのエントリです。昨日の小田さんに続き、私は、1μmも役には立たないエントリとなります !
最近思うこと
昨今、データベースシステムを構成するハードウェアは大量のコア、一昔では考えられないほどの大量のメモリーが搭載し、さらにデータベースのボトルネックの王者たる風格さえ漂っていたI/Oにも高速化の波が押し寄せてきています。そんな中、古くて新しい、そして、RDBMSとしての真価を問われるコンカレンシーの問題がボトルネックとして浮かび上がっているような気がしています。
このコンカレンシーの問題は、曲者で、どんなに高速なCPUを沢山搭載しても、どんなに沢山のメモリーを積んでも、ロケットばりの高速ストレージを使っても、コンカレンシーがボトルネックとなると全くパフォーマンスがスケールしません。(まぁー、極端な言い回しですが)
そんな事を、つらつら考えつつ、コンカレンシーの問題が大きく関係するBuffer Cache上で繰り広げられる様々な動きを考えて見ることにします。
ここで、登場するボトルネックの原因となるWait Eventは、こんな物です。
- latch: cache buffers chains
- latch: cache buffer lru chain
- free buffer waits
- read by other session
まず、SELECT文のEXEC/FETCHフェーズを想像して下さい。
上記のWait Eventを噛み砕くと、こんな感じでしょうか?
latch: cache buffers chains
「僕の探しているブロックはキャッシュされていますか~」を多くの人(Session)が聞きたがっている。でも、キャッシュされているか答えをもらうためのチケット(cache buffers chains latch)は一つ(もしくは非常に少ない)なので、なかなか、その順番が回ってこない。なので、「待つ」* ちなみに latch: cache buffers chains は"聞く"だけなら、コンカレンシーの問題は起こらないのですが、このラッチは、「ブロックをキャッシュするので、ちゃんと管理しておいて~」の場合には、他の人が触れないようにする必要がある("聞く"こともできない)ので、コンカレンシーの問題が発生します。
latch: cache buffer lru chain
先ほどのキャッシュされているか答えてもらうチケット(cache buffers chains latch)を使って、「そのブロックはキャッシュされてないです」と分かった場合、ディスクから目当てのブロックを探して、バッファ・キャッシュに乗せる必要がある。でも、バッファ・キャッシュのどこにでも乗せて良いわけがなく、「バッファ・キャッシュの空いてる場所はどこですか~」を多くの人が聞きたがっている。でも、空いている場所を教えてもらうためのチケット(cache buffer lru chain latch)は一つ(もしくは非常に少ない)なので、なかなか、その順番が回ってこない。なので、「待つ」
free buffer waits
さらに、「バッファ・キャッシュの空いてる場所はどこですか~」で空きがあれば良いのですが、「残念ながら空きはないです」と言われると、バッファ・キャッシュ上で、あまり使ってないだろうと思うブロックを捨てる。でも、その捨てようとしたブロックが、ダーティ・ブロックだった場合、DBWRに「これ、ダーティなので、データファイルにちゃんと書いといて」とお願いする必要がある。で、その書き出しが終わって、「使っていいよ」と言われるまで、「待つ」read by other session
さらにさらに、上記を経て、待ちに待った、キャッシュの乗せる作業に移るわけですが、面倒なことに、「今まさに、バッファ・キャッシュに乗せようとしている、そのブロック、そう、そのブロックを僕にも下さい」と他の誰かが言い出した。今、まさに、バッファ・キャッシュに乗せようとしている人は、ディスクから持ってこようとシングル・ブロック・リード(db file sequential read)やマルチ・ブロック・リード(db file scattered read)で頑張っている最中。なので、他の誰かは、「待つ」
ちなみに2セッションで、同一テーブルをフルスキャンすると1つのセッションはdb file scattered readで頑張り、もう1つのセッションはread by other sessionで待つ。という、なにか、こう、切ない感じがするのは私だけでしょうか...
ということで
ということで、キャッシュ上のブロックの管理も一苦労なわけで、それを、一度に沢山の人にお願いされると、コンカレンシーの問題が浮上するわけです。
最初の話に戻りますが、多くのCPUにより多くのセッションを同時に処理することが可能になるわけです。しかしながら、CPU間の同時実行から特定のリソースを保護する必要はあるわけで、CPUパワーを上手く使うことができない残念な結果も発生してしまいます。
ただこれば、今まではディスクのI/Oがボトルネックだ。とか言って見えていないコンカレンシーのボトルネックがハードウェアに進化とともに、また、というか、昔とは別の意味で見えてきたということでしょう。
ただこれば、今まではディスクのI/Oがボトルネックだ。とか言って見えていないコンカレンシーのボトルネックがハードウェアに進化とともに、また、というか、昔とは別の意味で見えてきたということでしょう。
ハードウェアが進化して、単純な問題は解決され、より複雑なデータベース自体の実装周りの問題が、今後のチューニング対象となっていくんだろうと思う、今日この頃です。
検証でのお話ですが、CPUネックになると library cache: mutex X が多くなったことがありました。この辺もデータベース実装と絡むのでチューニングが大変だろうなあ…と感じますね。
返信削除