データベース基本実行手順について調べたことまとめ

created_at:
updated_at:

目次

rails を書いてるとまず SQL に触れる機会がない

僕は業務で rails を扱っている。とても良いフレームワークだと思っているし、書いていて楽しい。

rails には find というメソッドがある。

User.find(1)

こんな感じで、DB からレコードを取り出すことができる。

実際は内部で以下の SQL が発行されている。

SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]

正直 find が使えれば特に困らないじゃん。と思うかも知れないが、find のような ActiveRecord で用意してくれているメソッドを使う際、エンジニア側が意図する SQL が発行されておらず、パフォーマンスが悪い SQL を実際は発行してしまっていた。なんてことがあるかもしれない。内部処理を理解し、意図した動作をさせることは一人前のエンジニアであれば当たり前なはずだと思って、今日も調べる。

SQL の処理

大まかな流れは以下のようになっている。

  1. SQL 文の解析
  2. SQL 文の最適化
  3. SQL の行ソース生成
  4. SQL の実行

SQL 文の解析

アプリケーションが SQL 文を発行すると、アプリケーションは Oracle Database は解析コールを出し、文の実行を準備する。

解析コール時はデータベースで以下のチェックを実行

  • 構文チェック

Oracle Database は各 SQL 文の構文上の妥当性を必ずチェックする。 SQL 構文の形式が整っていても、規則に違反している文はチェックが失敗する。

  • セマンティクス・チェック

文のセマンティクスとは、文の意味のこと。 セマンティクス・チェックでは、文内のオブジェクトおよび列が存在するかどうかなど、文の意味が有効かどうかを判断。

  • 共有プール・チェック

共有プール
SQL 文その他の情報データやキャッシュを配置する場所。

共有プールを利用することで、以下のようなメリットが得られる。

  • SQL 文解析のオーバーヘッドを回避
    • システムの CPU リソース低減・処理速度の向上
  • 共有プールにデータやキャッシュが残っていれば、データ確認が完結するため、ディスク・アクセスが不要となる。
    • ディスク I/O の総数が低下(処理速度の向上)

共有プール解析
実行しようとしている SQL 文と同じ SQL 文が、共有プール内に存在しているかをチェックすること。

共有プール解析を行うために、共有プール内に保管された各 SQL には、

あらかじめハッシュ・アルゴリズムを利用した ID がつけられている。

ユーザにより SQL が発行されると、発行された SQL をハッシュ化して ID を割り出して、

共有プール内の SQL 用の領域(共有 SQL 領域、または、カーソル・キャッシュ)を検索し、一致する SQL ID があるかを確認するしくみとなっている。

共有 SQL 領域に、一致する SQL があるかないかで、その後の解析処理が変わってくる。

  • 共有 SQL 領域に、一致する SQL 領域がなかった場合
    • 「ハード解析」と呼ばれる解析処理が走る。具体的には、新しい実行可能なバージョンのアプリケーション・コードを構築する処理が行われる。
  • 共有 SQL 領域に、一致する既存の SQL があった場合
    • 「ソフト解析」と呼ばれる解析処理となる。ソフト解析の場合、基本的にはその後の処理が大幅に省略され、一致した既存の SQL を利用することになる。
    • ただし、SQL が一致していたとしても、例えば以下のようなケースの可能性もある。
      • A スキーマ内の、 SELECT * FROM TESTTABLE;
      • B スキーマ内の、 SELECT * FROM TESTTABLE;
    • このように、まったく同じ SQL であっても、実際の意味としては異なる内容となっていることがある。そのため、既存の SQL 利用を最終決定する前に、本当に SQL が一致しているかを、より精密にチェックする処理が行われる。

より精密なチェックを経てもなお、共有 SQL 領域にある SQL と一致すると判断されれば、 次の「最適化」および「行ソース生成」の手順は省略される。 逆に、一致しないと判定されれば、ハード解析に強制的に切り替えられることになる。

SQL 文の最適化

Oracle Database は、一意の DML 文ごとに必ず 1 回以上のハード解析を実行して、この解析中に最適化を実行

SQL の行ソース生成

オプティマイザから最適な実行計画を受け取り、データベースのその他の部分で使用可能な反復実行計画を作成する

オプティマイザ
ソフトウェアやシステムの実行に関わる処理やデータを目的に応じ最適化するという DBMS が備える機能のこと。個々のクエリーの実行に際して要する手順の数やハードウェアのリソースを検討し、最も効率的な処理方法を選択する。

行ソース(行を反復的に処理できる制御構造に沿って、実行計画のステップから戻された行セット)

行ソース生成により、以下のような情報を持った「行ソース・ツリー」が作られることになる。

  • SQL 文によって参照される表の順序
  • SQL 文で出てくる各表へのアクセス方法
  • 結合される表の結合方法
  • フィルタ、ソート、集計などのデータ操作

実行

お疲れ様でした。

まとめ

勉強をすすめる中でオプティマイザが一番大事らしいので、そこを次回は深堀りしたい。 図解簡単にできればないいのになと思っている。何か良い方法ないかな。

参考資料

Buy Me A Coffee