パフォーマンス問題の犯人探し?
情報システムに問題(特にパフォーマンス問題)が発生した場合、運用を担っているインフラ・チームが真っ先にやり玉に挙げられることが多いようです。
そんな時のアプリ・チームの主張は
- 自分たちはアプリケーションに一切手を加えていないので悪くない。悪いはずがない。
- インフラ・チームが何かやらかしたのではないか?(過去に痛い経験があればなおさら)
- 隠しパラメータみたいな秘密のスイッチがあるらしいから、それをうまく使って切り抜けてくれ!
- インフラには高い金をつぎ込んでいるのだから何とかしろ!
というようなものが多いのではないでしょうか?
しかも、大抵の場合アプリ・チームの方が人数が多いので、多勢に無勢いつの間にか問題はインフラ・チームのせいになってしまっている、というようなことはよくあります。
最近は、新卒でインフラ・チームに配属されるというケースも多くなっていますが、ベテラン開発者から運用者に転向しているような技術者は総じてスキルのレベルが高いので(好意的に解釈して)重要な問題の解決を期待されているということの裏返しなのかもしれません。
ただし、インフラ・チームの名誉のために補足しますが、私はパフォーマンス問題の8〜9割近くはSQLつまりアプリケーションの問題のような印象を持っています。(なぜアプリケーションに手を加えていないのに問題が発生するのかは改めて触れたいと思います。)
DBAは問題解決の要
DBAは多くの場合インフラ・チームの一員として数えられていますが、データベースはミドルウェアと言いながらOSから見れば一種のアプリケーションであるので、DBAがアプリ・チームとの仲介役としてうまく機能できれば問題解決に対して非常に強い組織になります。
専任のDBAを置いている組織は少ないかもしれません。サーバ管理者が兼任していたりしてDBAの職務が曖昧になっている場合、インフラ・チームとアプリ・チームの溝が深くなってしまうことはよくあります。
DBA自らがアプリケーションを理解する
問題が発生してからアクションを起こすのでは遅すぎます。DBAは常日頃からアプリケーションに対して関心を持つ必要があります。理想的にはアプリ・チームの責任としてDBAが理解できるドキュメントを整備するのがベストですが、現実的にはなかなか難しいことが多いかと思います。
従って、DBA側から能動的に情報を収集することが必要です。DBAから見た最も身近なアプリケーションはSQL文です。Oracleでは実行されているSQL文に関するさまざまな情報をV$SQL*ビュー(Oracle11gR2であれば30種)から得ることができます。
V$SQL_PLAN
それではV$SQL_PLANを使用してSQL文とテーブルの相関表を作ってみましょう。あるSQL文がどのテーブルを使用しているか、あるいはあるテーブルはどのようなSQL文によって使用されているかを一覧にしたものです。これはDB設計におけるCRUD表に近いものですが、実際に動いているSQL文の情報を使って作るというのがポイントです。
実行計画のおさらい(SELECT)
以下の簡単な実行計画の例で考えてみます。
----------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ----------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 3 | 189 | 10 (10)| | 1 | NESTED LOOPS | | 3 | 189 | 10 (10)| | 2 | NESTED LOOPS | | 3 | 141 | 7 (15)| |* 3 | TABLE ACCESS FULL | EMPLOYEES | 3 | 60 | 4 (25)| | 4 | TABLE ACCESS BY INDEX ROWID| JOBS | 19 | 513 | 2 (50)| |* 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | | | | 6 | TABLE ACCESS BY INDEX ROWID | DEPARTMENTS | 27 | 432 | 2 (50)| |* 7 | INDEX UNIQUE SCAN | DEPT_ID_PK | 1 | | | -----------------------------------------------------------------------------------
まず中程の「Name」列は、その実行計画でアクセス(SELECT)されるテーブルあるいはインデックスとなります。テーブルなのかインデックスなのか名前から判断することもできますが確実なのは左隣りの「Operation」列が
- TABLE ACCESS で始まっているものが「テーブル」
- INDEX で始まっているものが「インデックス」
です。
V$SQL_PLANからSELECT対象のテーブル一覧を取得する
V$SQL_PLANから情報を取得するクエリーを考えてみます。
select distinct SQL_ID ,OBJECT_NAME ,3 CRUD_TYPE_ID ,OPTIONS from V$SQL_PLAN where OPERATION like 'TABLE%' and OBJECT_OWNER = 'xxxx' order by OBJECT_NAME ,CRUD_TYPE_ID ,SQL_ID;
8行目のWHERE条件でテーブルアクセスのオペレーションのみを取り出しています。
9行目ではテーブルの所有者で絞り込みをしています。
4行目で何をしているのかというと、V$SQL_PLANにはない V$SQL.COMMAND_TYPE に相当する情報をここで付加しています。
SELECTであれば「3」になります。この理由は追って説明します。
以下は実行例です。
SQL> select distinct 2 SQL_ID 3 ,OBJECT_NAME 4 ,3 CRUD_TYPE_ID 5 ,OPTIONS 6 from 7 V$SQL_PLAN 8 where OPERATION like 'TABLE%' 9 and OBJECT_OWNER = 'SCOTT' 10 order by 11 OBJECT_NAME 12 ,CRUD_TYPE_ID 13 ,SQL_ID; SQL_ID OBJECT_NAME CRUD_TYPE_ID OPTIONS ------------- ------------ ------------ -------- 0cc0hqvr7kpgx BONUS 3 FULL 30hdyzpfrzgbf BONUS 3 FULL 3154rqzb8xudy DEPT 3 FULL 678kpdu03jc8x DEPT 3 FULL 1srhq04p4x0zz EMP 3 FULL a2dk8bdn0ujx7 EMP 3 FULL 25tuw6725a9h7 SALGRADE 3 FULL 30p00zk91247c SALGRADE 3 FULL 8行が選択されました。
(続く)