福岡寿和 FUKUOKA, Toshikazu
さて,一般にデータベースの構造には,
・ISAM(索引順アクセス方式:AccessのMDBなど)
・NDB(ネットワークデータベース方式:おもにホストコンピュータで普及)
・RDBMS(リレーショナルデータベース方式)
・OODBMS(オブジェクト指向データベース方式)
などがあります.しかし,現在ではデータベースといえばRDBMS,というほどRDBMSが普及しています.これは,メーカーごとに差異があるとはいえ,RDBMSはSQLという標準言語により操作可能な点が大きいと思います.SQLさえ覚えれば,とりあえずRDBMS上のデータを何らかの形で検索して取得できる垣根の低さがあるわけです.しかし,RDBMSを有効に活用するためには,どのようなRDBMS製品でも共通に乗り越えなければならない問題や製品ごとに異なる諸問題を解決しておかなければなりません.そのためにも,きちんとした設計とRDBMSに合わせたミドルウェアの選択が必要不可欠です.
| I | RDBMS設計のポイント |
|---|
| 設計工程1 |
| -現状分析からあるべき姿を設計する- |
Visual BasicなどのRADツール(作りながら設計してゆく)がWindowsプログラムの主流になったために,スパイラルフロー(メイク・アンド・トライ)型の開発スタイルが流行になっています.しかし,RDBMSの設計に関しては,従来のウォーターフォール型の設計を行なう必要があると感じています.つまり,RDBMSを使ったシステムでは,その上に実装されるデータ構造の善し悪しがシステム開発の成否を握っていると思うからです.
では,よいデータ構造はどのように設計したら実現できるのでしょうか.
現状把握
図1:BP(ビジネスプロセスダイアグラム)
|
プロセスモデリング
現状を把握したものを分析するには,システム化しようとする対象を抽象化して,その抽象化したもの同士の関係(情報の流れ)を明確化してゆく作業が必要です.この作業をモデル化といい,この時に使われるのがBP図(ビジネスプロセスダイアグラム:図1)です.
BP図で重要なのは,業務上どの情報がどこでいつ発生し,どう利用されるかという点を明確にすることです.そのため,BP図にはコンピュータ上の情報や作業ばかりではなく,たとえば,「手紙を書く」―(郵送する)→「手紙を読む」などの作業も記述します.また,プロセスモデリングの手法のなかには,BP図ではなく,HER図(ハイレベルエンティティリレーションシップダイアグラム)を使うものもあります.
BP図,HER図のどちらを使うにしても,プロセスモデリングの基本は業務担当者へのインタビューによる現行業務の理解です.このインタビューが一番重要なのですが,インタビューを定量的に判断する指標やツールがないために設計担当者の手腕に左右されやすいところです.また,実際の利用部門ではなく,情報システム部門の担当者へインタビューしたときや,実際の利用部門の職員でも現行業務の遂行者ではなく,パソコンに詳しい「新システム担当」の職員のときは,「コンピュータならばこうだろう」という先入観に基づいて,自分なりにシステムを最適化した形でインタビューに答えることがあります.これは善意から発生した行為なのですが,きちんとした全体像を押さえてモデリングするときには妨げになります.プロセスモデリングを行なうときは,まず現状を正しく表記するために,真実を白日の下にさらす話術というかコミュニケーション能力が必要になってくるでしょう.
図2:DFD(データフローダイアグラム)
|
システムモデリング
システムモデリングでは,プロセスモデリングでの分析結果を基にして,「どのように情報が管理されているか」を分析するプロセス分析と「どんな情報が必要とされているか」を分析するデータ分析を行ないます.
プロセスモデリングでは,組織という側面からプロセスをモデル化しました.しかし,組織というものは固定的なものではなく,現代の企業ではドラスティックに変化してゆきます.そこで,プロセスと組織をいったん分離して,プロセス間のデータの流れに注目したうえで,組織変更の影響を受けない形での検証をします.このときに用いられるのがDFD(データフローダイアグラム)です(図2).
図3:ER(エンティティリレーションシップ)図
|
データ分析
BP図やDFDでは,あくまで帳票などの現実に存在する形でしか「どのような情報が必要とされているか」を表現できません.データ分析では,BP図やDFDでモデル化した情報について,そのデータ構造やさまざまな情報との関連を設計してゆく作業を行ないます.この時に使われるものが図3のER(エンティティリレーションシップ)図です.エンティティはよくテーブル設計と誤解される時がありますが,正確には複数の物理テーブルを含むこともあります.エンティティはあくまでも情報単位であり,そこには,各RDBMSのチューニングノウハウを反映する必要はありません.あくまでもシステム上の情報単位を念頭に置いて,最初は設計すればよいでしょう.
データ分析で難しいのは,ER図のもうひとつの局面であるエンティティ間の関係(リレーション)を定義することです.この関係の理想的な姿は,ER図で表記した時に冗長データがない姿になります.つまり,冗長データがない形が定義できれば,それは「システムで管理される理想的なあるべき姿」になります.では,理想像が単純に「冗長データがない」ことなのになぜ難しいのでしょうか.それは,あるデータが冗長か否かはビジネスロジック(業務知識)に大きく依存するからです.一般常識で想像できる範囲にあればよいのですが,たとえば業界特有のビジネスロジックが必要であったり,そのシステムを導入する企業や部門特有のビジネスロジックが必要なときもあります.
しかし,標準的な手法がまったくないわけではありません.正規化という手法を使うことで,あるべき姿を追求することができます.
| 設計工程2 |
| -あるべき姿の追求(正規化)- |
現実世界の情報を任意の単位にまとめただけでは,効率的なデータ構造を作ることはできません.それは,人の目に触れる情報が人が理解しやすい形で加工されているからです.しかし,人が理解しやすい形が必ずしもRDBMSを効率的に使う形であるとは限りません.たとえば,発注書は,「発注」という側面に注目した情報の固まりです.発注したものがひとつであったり,一度で納品できればよいのですが,現実的ではないため,納品時には納品書という別の側面に注目した伝票が発生しています.このように同じ情報をその情報を見る側面ごとにRDBMSに格納すると,2つの情報間でデータのコピーが頻繁に発生したり,「未納品の製品は?」といった新たな側面で情報を取得するのが難しいデータ構造ができあがります.これでは,RDBMSを使ったシステムをわざわざ導入する意味がありません.設計時にすら気が付かなかった切り口で情報を分析できることがRDBMSの利点のひとつですから,その利点を生かすようなデータ構造に設計する必要があると思います.そのような設計を助ける手法が正規化であり,システムモデリングのフェーズでER図を使って作業します.
正規化には第一正規化から第三正規化まであって,すべての正規化が完了した第三正規形の表では,データ項目の冗長性(無駄な部分)がまったくありません.つまり,無駄なデータコピーなどが発生することが不可能な状態になります(図4).
|
図4:正規化の過程 図5:口座情報の正規化 |
第一正規化図4では,「FAQ」から「回答履歴」を分離しています.通常FAQの回答はひとつですが,ここでは,「過去にどのような回答の誤りがあるのか,また,いつ回答が変更されたかがわかるようにして欲しい」というユーザーからの要望に対応するデータ分析結果により発生した繰り返し項目です.このように一般常識と個々の業務要望が異なるときもあるので,プロセスモデリングできちんとヒアリングをしておく必要があります.同様にカテゴリを表わすキーについても現在は4つですが,増減することがヒアリングから判明したときは,その部分も第一正規化を行ないます.
第二正規化
主キーが複数の項目になっているとき(複合キー)は,そこに含まれる項目に主従関係が存在します.この主従関係に注目するのが,第二正規化です.
図4では,カテゴリキーの分類(キーNo=1→Oracle7)をマスタ化することに伴なって,第二正規化が行なわれています.
もう少しわかりやすい例としては,銀行の口座情報があります(図5).
第三正規化
第三正規化は,キーから独立した他の項目を分離する正規化です.図4では,分析の結果として,複数の質問の回答が同一になる可能性があるので,「回答」に対して「回答CD」を割り当てて,回答マスタを分離しています.
最適化
第三正規形の表を見比べてみると,主キーが同一項目の表が複数存在するときがあります.ERDの解説書の中には,このような表をひとつの表にまとめる工程が書かれているときがあります.確かにビューという仮想的な表を使って,複数の表をひとつに見せるよりも物理的にひとつの表にした方が,主キーの領域を節約できるため,ディスク領域を効率的に使えます.また,ビューを使って更新することができなかったので,プログラムも簡単になるという利点もあります.しかし,Oracle7 R7.3では,条件さえ満たせば更新可能なビューを定義することができます.また,主キーが同一項目でも,更新する部門が異なる場合などには,表が分割された分析結果が発生している可能性もあります.このようなときは,必ずしも主キーが同一項目の表をまとめることがシステム全体として効率的にならないときがあります.RDBMSの機能にもよりますので,第三正規形の表の最適化は正規化の工程ではなくシステムデザイン工程で行なう作業なのかもしれません.
| 設計工程3 |
| -あるべき姿をRDBMS上に表現する- |
システムデザイン
| II | First[Oracle]Contact |
|---|
| Oracle7の製品系列 |
さて,RDBMS一般に関する解説はひとまずおいて,そろそろOracleに特化した話題にうつりましょう.OSとOracle7 R7.3製品系列を図6にまとめました.Oracle7シリーズは,オプションや最新機能の一部を除いて,同一のアーキテクチャを採用していますので,テーブル定義を同一にしておけば,Personal Oracle7と接続していたソフトをOracle7 Serverと接続して使うなどといったことも可能です.
ところで,Visual Basicなどのマイクロソフト製品になれた人は,ソフトウェア製品の識別にバージョン番号を使いますが,Oracleはリリース番号を使います.そして,通常,先頭の2つが仕様ごとの番号になります.ですから,R7.2とR7.3では機能面でかなりの違いが見られるので,箱や広告などにもこの2つの番号までを記載しています.しかし,内部的にはさらに2つの番号を付加して,R7.3.2.3のように表記し,バグフィックスや機能制限の種類などをあらわしています.Oracle7を使ったアプリケーションを作るときに,開発環境と実行環境を同一にするためには,この4桁の番号まで(さらにオプションソフトウェアの導入状況まで)意識した方がよいでしょう.
さらに,混乱が生じてしまうと思われるのは,いままで説明してきたリリース番号は,製品パッケージに対する識別番号で,パッケージに含まれるそれぞれのソフトウェアには,おなじみのバージョン番号が使われている点でしょう.たとえば,Personal Oracle7 R7.3.2.3のデータベースエンジンは,Oracle7 Database V7.3.2.3.1です.そして,同じリリースの製品パッケージでもそこに含まれているソフトウェアのバージョン番号などが異なることがある点です.これでは,かなり煩雑なバージョンの確認が必要になってしまいます.在庫を多く抱えてしまった納入業者を経由して購入したりすると先頭2つのリリース番号は同じでも内容が古いものがきてしまう可能性もあります.この問題をCD-ROMの袋を開けずに簡単に判断する方法はないのでしょうか.実は,箱の裏の標準価格の側に「A46403-1」などと記載されているのが,CD-ROMの版数まで含めた「製品番号」なのです.この最新番号をOracleのWebPageや電話などで確認することで,手元の製品が最新かが判断できます.
Personal Oracle7
Personal Oracle7(PO7) R7.3からはWindows NTも動作プラットフォームとして加わったOracle7シリーズのシングルユーザー専用RDBMSです.PO7の主な用途としては,
・スタンドアロンRDBMSシステムの構築
・データ複製機能を使った分散RDBMSシステムの構築
・ノートパソコンと組み合わせたモバイルRDBMSの構築
などが考えられます.
PO7を使うとき,PO7が稼動しているパソコンへネットワークを通して同時にログインできるのは1ユーザーのみに制限されている点に注意してください.これは,PO7がシングルユーザー用RDBMSであるためです.また,Windows95で使ったときのみですが,PO7 R7.3(R7.3.2.3 A46113-1)では,ログインするたびに10Kバイトずつメモリがリークします.原因はWindows95側にあるようですので,修正されるのは望み薄かもしれません.この制限事項を考慮してシステム提案するかWindows NT上でシステムを構築することをお勧めします.
Oracle7 Workgroup Server
Oracle7 Workgroup Server(Oracle7 WGS)R7.3は,Microsoft SQL Serverと市場を争っている製品です.そのため,かなり戦略的な価格設定が行なわれていて,利用者にとっては嬉しい限りです.そして,機能面でもOracle7 Serverの前バージョンで好評だった機能を積極的に取り入れることなども行なわれています.Oracle7 WGSは,そのような外的要因が作用して,「1台のRDBSMサーバーでカバーできる業務ならば,部門単位から全社単位の業務にまで適用できる」という位置づけがぼやけてきている感じがします.Oracle8では,ワークグループサーバーという名称ではなく,Oracle8 Serverという名称に変更し,本来の位置づけにそった機能を明確にして,Oracle8 Server Enterprise Edition(Oracle8 Server EE:現Oracle7 Serverの後継)との差別化が図られています(図7).
図7:Oracle8製品体系
Oracle7 Server
Oracle7シリーズの旗艦であるOracle7 Serverは,OracleがRDBMSをどのように進化させたいかを判断するのに適切な製品です.価格的にも旗艦に相応しいものになっているので,試用導入もなかなか大変かもしれませんが,その動向に注意していると,次期バージョンでどのような拡張がOracle7 WGSに行なわれるかが見えてくると思います.
| Oracle7概要 |
Oracle7の動作単位をインスタンスといいます.このインスタンスの構造を知ることが,Oracle7を知ることに繋がると思いますので,少し詳しく説明しておきましょう.
Oracleインスタンスは,図8のような構成になっていて,その中心的役割をになっているのがシステムグローバル領域(SGA)と呼ばれる共有メモリ領域です.
プロセス
ひとつのOracleインスタンスを起動すると複数のプロセスが起動します.そしてこのプロセスはすべてSGAを介して情報をやりとりします.
また,シャドウプロセスといって,Visual Basicで作成したプログラムや各種ツール(ユーザープロセスといいます)とOracleインスタンスとの間で情報を受け渡す役目を果たすプロセスもあります.このシャドウプロセスは,基本的に1ユーザープロセスが接続してくるごとにひとつ生成されます.
メモリ
Oracleインスタンスが使うメモリ領域には,SGAとPGA(プロセスグローバル領域)があります.SGAは,Oracleインスタンスのスタートアップ時に全体が割り当てられます.SGAのサイズは,SGAに割り当てられている3種類のメモリ種別のサイズをinit[SID].oraという設定ファイルの
\ORANT\Database
にあり,[SID]は,インスタンス名になります.たとえば,デフォルトデータベースでは,initORCL.oraになります.
PGAは,シャドウプロセスが独自に使うためのメモリ領域です.PGAには,現在オープン中のすべてのカーソル情報,共有プールにある解析済みのSQL文へのポインタなどが格納されています.PGAは,シャドウプロセスが起動されたときに割り当てられて,接続が解放されるまで存在します.
ファイル
Oracle7には大別して3つのファイル形式があります.
データベースファイル
データベースファイルには,表や索引のユーザーデータファイル以外に,システムファイルも含まれます.データベースファイルに対しては,シャドウプロセスから読み書きできます.
REDOログファイル
REDOログファイルとは,Oracle7に対して実行されたすべての変更内容を記録したログを記録するファイルで,読み込み時の一貫性やロールバックを実行するときにも使われます.
制御ファイル
制御ファイルは,Oracle7の中核となるファイルです.そのため,制御ファイル定義で物理ファイル名に別ハードディスク上の複
数のファイルを指定して,ディスク障害の影響を受けないように注意する必要があります.
共有プール
共有プールには,SQL文の解析結果が格納されます.大文字小文字や空白の数も含めてまったく同一のSQL文を使うときは,解析過程(SQL文のチェック,解析ツリーや実行計画の作成)が省略され,速度の向上が望めます.この領域は複数のアプリケーションで同時に使われるので,「SQL文の予約語や関数はすべて大文字,空白はひとつフィールド名やテーブル名は仕様書通りに大文字小文字まで意識する」などのコーディング規約を作るだけでもアプリケーション全体の動きがスムーズになる可能性を秘めています.
| 新規データベースの生成 |
(1)init[SID].oraの用意
SIDがVBMのインスタンスを作成するならば,“init.ora”を“initVBM.ora”という名前でコピーしてこのinitVBM.oraを編集するのが手軽でしょう(リスト1).また,インスタンスとOracleデータベースの関係が分かりやすいように,IDとDB_NAMEパラメータの値を同一にするのがよいと思います.なお,コピー後に変更するパラメータの代表例を表1にまとめました.
リスト1:initVBM.ora(抜粋)]
db_name=VBM control_files = (D:\VBM\ctl1VBM.dbf,D:\VBM\ctl2VBM.dbf) rollback_segments = (rbs1, rbs2,rbs3,rbs4,rbs5,rbs6,rbs7,rbs8) db_files = 1024 db_file_multiblock_read_count = 16 log_buffer = 32768 shared_pool_size = 9000000 db_block_buffers = 550 log_checkpoint_interval = 10000 processes = 100 parallel_max_servers = 5 db_block_size = 2048 |
表1:初期化パラメータ(SGAメモリパラメータを除く)
| パラメータ | 意味 |
| DB_NAME | コマンド実行時にオープンされるデータベース名.8文字以内 |
| CONTROL_FILES | 制御ファイルの名前.複数指定して,制御ファイルをミラー化した方がよい |
| ROLLBACK_SEGMENTS | ロールバックセグメントを作成したらここに記述することで,インスタンス起動時に自動的に使用可能になる |
(2)Oracleインスタンスの生成と起動
initVBM.oraの編集が終わったら,Oracleサーバーマネージャを使ってインスタンスを起動します.サーバー上の
\ORANT\BIN\SVRMGR23.EXE
がサーバーマネージャです.このEXEを起動すると
SVRMGR>
とプロンプトが表示されるので,
SVRMGR>CONNECT INTERAL
SVRMGR>STARTUP NOMOUNT PFILE=…(中略)…\initVBM.ora
と入力して,インスタンスを起動します(インスタンスがないときは環境生成も行なわれます).
(3)Oracleデータベースの作成
(1)でNOMOUNTモードでインスタンスが起動したら,Oracleデータベースを作成します.作成には,CREATE DATABASE文(リスト2)をSVRMGRから入力します.あらかじめ,CRTDB.SQLという名前でSQLスクリプトをファイルとして保存して,
SVRMGR>@\CRTDB.SQL
とファイル名指定でSQL文を入力することができます.入力ミスを防止するためにもSQLスクリプトを作成することをお勧めします.
CREATE DATABASE文の実行には,5〜6分かかります(環境にもよりますが).進行度合いは,SQL文で指定したDATAFILEの大きさをファイルエクスプローラなどで確認します.このSQL文の実行が完了すると図9のようなOracleデータベースが構築されます.
なお,データベース作成後,データディクショナリを参照するために,CATALOG.SQLとCATAPROC.SQLのSQLスクリプトを実行します.
図9:Oracleデータベースの作成
リスト2:データベースの生成用SQL文
CREATE DATABASE VBM
CONTROLFILE REUSE
LOGFILE GROUP1
('D:\VBM\log11VBM.DBF','D:\VBM\log12VBM.DBF') SIZE 10M REUSE,
GROUP2
('D:\VBM\log21VBM.DBF','D:\VBM\log22VBM.DBF') SIZE 10M REUSE
DATAFILE
'D:\VBM\sysVBM.DBF' SIZE 80M REUSE
CHARACTER SET JA16SJIS;
|
(4)ダミーRollbackセグメントの作成
SYSTEM表領域は,あくまでもOracleのシステムが動作するうえで必要な最小限度のデータ(図9にあるようにデータディクショナリとシステムロールバックセグメント)以外には使用しない方がよいでしょう.ですから,アプリケーションが使うテーブルを格納するのは,SYSTEM表領域以外に表領域(ユーザー表領域)を作成します.ユーザー表領域を作成する前作業として,一時的なロールバックセグメントを作成します.これは,「1データベースに複数のテーブルスペースが存在するときは,2つ以上のロールバックセグメントが必要」という仕様があるからです.CREATE DATABASEでシステムロールバックセグメントは作成されているので,もうひとつロールバックセグメントが必要になるので一時的なものをSYSTEM表領域に作成します.
SVRMGR>CREATE ROLLBACK SEGMENT drbs
2> TABLESPACE SYSTEM;
CREATE ROLLBACK SEGMENT文でロールバックセグメントを作成すると作成直後はオフライン(使用不可能)状態になっているので,
SVRMGR>ALTER ROLLBACK SEGMENT drbs ONLINE;
としてオンライン(使用可能)状態になります.また,initVBM.oraのROLLBACK_SEGMENTSパラメータに作成したロールバックを指定していないとデータベース起動時に自動的にオンライン状態になりません.ただし,ここで作成したdrbsは一時的に使うものなので,initVBM.oraに記述しません.
なお,ロールバックセグメントとは,RDBMSのレコードを更新中に
・UPDATE時には,UPDATE前の値
・DELETE時には,DELETE前の値
・INSERT時には,タグ情報とそれに対応したINDEXキー
の情報を保存しておく領域です.
(5)表領域の作成
テーブルデータやINDEXデータ,ロールバックセグメントを格納するユーザー表領域の作成は,CREATE TABLESPACE文で行ないます.表領域の作成もSQLスクリプト(リスト3)を用意しておくと作業がしやすくなるでしょう.ユーザー表領域を作成するとき,物理ディスクのどこに配置するかによりデータベースのパフォーマンスが変化する(物理配置の検討はチューニングの方法のひとつ)ため,実際のシステム構築ではテーブルデータやINDEXデータを格納する表領域をうまく分散させて,ディスクI/Oのボトルネックを回避します.PCをサーバーにするときは,SCSIカードも複数枚挿すなどのハードウェア的な並列化も考慮する必要があるでしょう.
表領域としては,最低でもユーザー表領域,索引表領域,一時表領域の3つの表領域を作成するとよいでしょう.とくに一時表領域は,ORDER BYやGROUP BYなどのソートが必要な処理が多いときの速度向上に効果があります.一時表領域は,
SVRMGR>ALTER TABLESPACE TEMP TEMPORARY;
として,テーブルスペース(例ではTEMP)を指定するSQL文を実行して割り当てます.
リスト3:表領域の作成
#ロールバックセグメント表領域 CREATE TABLESPACE rbs DATAFILE 'C:\VBM\rbs1VBM.dbf' SIZE 50M REUSE, DATAFILE 'D:\VBM\rbs2VBM.dbf' SIZE 50M REUSE DEFAULT STORAGE (INITIAL 100K NEXT 100K MINEXTENTS 2 MAXEXTENTS 121 PCTINCREASE 0); #一時表領域 CREATE TABLESPACE temp DATAFILE 'D:\VBM\tempVBM.dbf' SIZE 100M REUSE DEFAULT STORAGE (INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0); #デフォルト表領域 CREATE TABLESPACE tools DATAFILE 'D:\VBM\toolVBM.dbf' SIZE 10M DEFAULT STORAGE (INITIAL 10K NEXT 10K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0); #テーブルデータ表領域 CREATE TABLESPACE usr1 DATAFILE 'D:\VBM\usr1VBM.dbf' SIZE 80M DEFAULT STORAGE (INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0); CREATE TABLESPACE usr2 DATAFILE 'D:\VBM\usr2VBM.dbf' SIZE 80M DEFAULT STORAGE (INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0); CREATE TABLESPACE usr3 DATAFILE 'D:\VBM\usr3VBM.dbf' SIZE 80M DEFAULT STORAGE (INITIAL 100K NEXT 100K MINEXTENTS 1 MAXEXTENTS 121 PCTINCREASE 0); |
(6)Rollbackセグメントの作成
(3)と同様にCREATE ROLLBACK SEGMENTS文でロールバックセグメントを作成します(リスト4).ただし,今度はSYSTEM表領域ではなく,RBS表領域に作成して,そこで指定した名前をinitVBM.oraに記述します.
ロールバックセグメントの個数は,50を最大値として,
個数=同時更新数÷4
を目安としてください.
リスト4:ロールバックセグメントの作成
CREATE ROLLBACK SEGMENT rbs1 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs2 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs3 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs4 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs5 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs6 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs7 TABLESPACE rbs; CREATE ROLLBACK SEGMENT rbs8 TABLESPACE rbs; |
(7)データベースユーザーの作成
新規データベースの最後の作業は,そのデータベースを利用するデータベースユーザーの作成です.CATALOG.SQLのSQLスクリプトにより,デフォルトユーザーのSYSとSYSTEMが作成されますが,この2つのユーザーをテストには使わないでください.この2つはOracleのツール用のユーザーであると考えてください.独自のユーザーVBMAGを作成するSQL文はリスト5の通りです.ユーザー作成時の注意点はあまりないのですが,忘れがちなのはDEFAULT TABLESPACE句とTEMPORARY TABLESPACE句の指定です.この2つの句を指定しないと表領域名を省略したときにSYSTEM表領域にテーブルが作られます.必ず適切な表領域を指定するようにしてください.
リスト5:データベースユーザーの作成
CREATE USER vbmag IDENTIFIED BY pass DEFAULT TABLESPACE usr1 TEMPORARY TABLESPACE temp; |
(8)ロール(権限)の割り当て
さまざまな役職の人が使うことになるRDBMSでは,個人ごとに表の参照可否や更新可否を設定するのは効率的ではありません.役職ごとに権限を設定して,その役職を利用者に割り当て,利用者の役職が変更になったら,役職名を変更することで権限を切り替えるという考え方があります.Oracle7は,それをロールとして実装しています.
Oracle7にはデフォルトロールとして表2のようなロールがありますが,テスト以外では,自分で独自のロールを作成してそれを使うようにしてください.システム構築を始めたころはデフォルトロールと同じ権限でよかったものが,設計を進めていく過程で権限に変更が生じたときも,独自ロールであれば,柔軟に対応することができるからです.SYSTEMユーザーと同様にデフォルトロールについてもOracleのツール用ロールと考えてください.リスト6が独自ロールの生成と独自ユーザーへの割り当てのSQL文になります.この例のようにロールをロールに割り当てることも可能なので,お手軽に済ませたいときは,デフォルトロールを独自ロールに割り当てるだけでもよいと思います.
表2:デフォルトロール
| CONNECT |
| DBA |
| RESOURCE |
| EXP_FULL_DATABASE |
| IMP_FULL_DATABASE |
リスト6:ロールの作成と割当
CREATE ROLE vbm_roll NOT IDENTIFIED; GRANT DBA TO VBM_ROLL; GRANT VBM_ROLL TO VBM; ALTER USER VBM DEFAULT ROLE ALL; |
(9)ユーザー表(テーブル)の作成
以上の手順が完了すると,ユーザー表を作成する準備が整ったことになります.ユーザー表の作成もSQL文を使います.リスト7のSQL文を実行するとサンプルプログラムで使う表が作成されます.
| III | Visual BasicとOracle7 |
|---|
| ミドルウェアの選定 |
では,いよいよOracle7の主な機能を実際に使うために,まずVisual BasicからどのようにOracle7を使ったらよいかの検討に入りたいと思います.本来,SQL*Netもミドルウェアの範疇に入るのですが,現状を考えてみるとTCP/IPとSQL*Netの組み合わせが事実上の標準であるので,この2つについては今回はミドルウェアの範疇からは除外して,SQL*Net ClientとVisual Basicの間に位置する(まさにミドル)ソフトの選択に的を絞ってみたいと思います(図10).なぜなら,ここに位置するソフトウェアは,MicrosoftとOracleという異なるメーカー間の調整役となるもので,システム全体の機能,安定性そしてレスポンスなどを左右するほど重要なものだからです.
図10:ミドルウェアの技術分割図
|
図10に記載しているミドルウェアを使うには,以下のような操作を実行します.
ping サーバー名
になります.もし,サーバー名でReplyが返ってこないときは,クライアントとサーバーの通信環境を再チェックしてください.
(2)SQL*Net Easy Configurationの実行
PINGが通ったならば,次はTNSプロトコル(SQL*NetV2.xの独自プロトコル)の接続定義を行ないます.TNSプロトコルの定義は,SQL*Net Easy Configurationを使ってサーバー名とインスタンス名を「データベース別名」で登録するだけです.TNSプロトコルの接続確認方法は,DOSプロンプト上から,OracleのBINディレクトリに移動して
TNSPING データベース別名
です.
なお,SQL*Netのサーバー側とクライアント側の組み合わせは,バージョンの先頭が一致する必要があります.SQL*Net V1は,R7.3以降には添付されていないので,接続文字列がプログラム中に埋め込まれているなど,クライアントソフトの作りが悪いときは,早急に対応する必要があります.
リスト7:ベンチマークテスト用テーブル作成
DROP TABLE VbFaqPcdn CASCADE CONSTRAINTS;
CREATE TABLE VbFaqPcdn (
FAQID char(8) NOT NULL,
FAQFreeCharge char(1) NULL,
FAQVbVer2 char(1) NULL,
FAQVbVer3 char(1) NULL,
FAQVbVer4_16 char(1) NULL,
FAQVbVer4_32 char(1) NULL,
FAQVbVer5 char(1) NULL,
FAQVbVer6 char(1) NULL,
FAQCategoryGeneral char(1) NULL,
FAQCategoryForm char(1) NULL,
FAQCategoryControls char(1) NULL,
FAQCategoryOcx char(1) NULL,
FAQCategoryOle char(1) NULL,
FAQCategoryDao char(1) NULL,
FAQCategoryRdo char(1) NULL,
FAQCategoryDbMisc char(1) NULL,
FAQCategoryPrint char(1) NULL,
FAQCategory16APIs char(1) NULL,
FAQCategory32APIs char(1) NULL,
FAQCategoryKeyWords varchar2(255) NULL,
FAQQuestion varchar2(255) NULL,
FAQAnswer varchar2(2000) NULL,
FAQAnswerAttach varchar2(50) NULL
);
ALTER TABLE VbFaqPcdn
ADD ( PRIMARY KEY (FAQID) ) ;
|
DAO/Jetを使う
Visual BasicからRDBMSを使おうとしたときに真っ先に思い付くのが,このDAO/Jetによるアクセスかもしれません(リスト8).DAO/Jetならば,Enterprise版を購入しなくてもPro版でも使うことができますし,何といってもODBCデータソースに切り替えるだけでAccess用に作ったプログラムがそのまま動くかのような誤解が横行しているのが原因でしょう.
はっきりいってDAO/Jetは,AccessのMDBファイルやテキストファイルなどのローカルファイルに対するミドルウェアであり,RDBMSに使うときには,帳票などでワンポイントリリーフ的に使うときに限定する必要があります.これは,Visual Basicだけではなく,Accessを使ったときも同様です.
DAOを使った方法には,DAO/Jet以外にODBC Directがあります.ODBC Directは,Visual Basic 5.0側からはDAOに見えるのに,内部的にはRDO2.0を使う方法です.決して,ODBCを直接使うものではありません.この機能は,DAO/JetでAccessに接続していたものを何とかして簡単にRDBMSとうまく接続する方法を模索した結果だと思います.Oracleに接続するときは,せめてDAO/JetではなくODBC Directを使ってください.
リスト8:DAO/Jetの利用
Dim wrkDAO As Workspace
Dim dbsDAO As Database
Dim rdynDAO As Recordset
Set wrkDAO = CreateWorkspace("Jet", "admin", "", dbUseJet)
Set dbsDAO = wrkDAO.OpenDatabase("VBM", False, False, _
"ODBC; UID=scott;PWD=tiger")
Set rdynDAO = dbsDAO.OpenRecordset("select * from VbFaqPcdn", _
dbOpenDynaset,dbSQLPassThrough)
Do While Not rdynDAO.Eof
Debug.Print rdynDAO("FAQID")
rdynDAO.MoveNext
Loop
rdynDAO.Close
dbsDAO.Close
Set wrkDAO = Nothing
|
RDOを使う
RDOは,その名前が示すようにRemoteDataつまりRDBMSに対応したミドルウェアです.言語仕様的には,RDBMSと接続するときにはDAO/JetではなくRDOを使うことが前提になっています(リスト9).しかし,Oracleに適用するときには,注意が必要です.それは,RDOがODBCをベースにした仕様であり,ODBCの仕様がSQL Serverの機能不足点を補うためやADOなどの新技術により次々独自拡張されて,Oracle7用のODBCドライバの開発とのいたちごっこになっている現状があるからです.このような状況を踏まえるとRDOは,SQL Server用のミドルウェアという位置づけでしかないのです.もし,それでもOracle7とRDOで接続するときは,Visual Basic 5.0に添付されているMicrosoft ODBC Driver for Oracleではなく,OracleのWebサイトから,Oracle7 ODBC Driver 2.0.3.2.9をダウンロードして使ってください.本稿の動作確認は,すべてこのODBC Driverにより確認しています.
リスト9:RDOの利用
Dim rdcnnRDO As rdoConnection
Dim rdrslRDO As rdoResultset
Set rdcnnRDO = New rdoConnection
rdcnnRDO.Connect = "DSN=VBM;UID=scott;PWD=tiger"
rdcnnRDO.CursorDriver = rdUseServer
rdcnnRDO.EstablisConnection rdDriverNoPrompt, False, 0
Set rdrslRDO = rdcnnRDO.OpenResultset("SELECT * FROM VbFaqPcdn", rdOpenKeyset)
Do While Not rdrslRDO.Eof
Debug.Print rdrslRDO("FAQID")
rdrslRDO.MoveNext
Loop
rdrslRDO.Close
rdcnnRDO.Close
Set rdcnnRDO = Nothing
|
この2つのODBC Driverのどちらを使うにしても,クライアント側のSQL Netは必ずSQL*Net Client 2.3以上が必要です.比較的長期間の開発になりがちなOracle7を使ったシステム開発では,Oracle7はR7.2で,Microsoft Office97やVisual Basic 5.0を導入してしまうときもあるかもしれませんが,そのようなときでもSQL*Net ClientのバージョンをV2.2からV2.3へバージョンアップする必要があります(SQL*Net Client 2.3とSQL*Net Server2.2の接続は保証されています).
Oracle7 ODBC Driver 2.0.3.2.9は本稿執筆時点で無料で入手できる最も安定したODBCドライバのひとつですが,Oracleインスタンスの環境設定によっては,Visual Basic 5.0が異常終了します.動作確認をOracle8 Server EEで行なったのが原因かも知れませんが詳細は不明です.このODBC Driverをインストールするときの注意点は,Oracle7 ODBC Driverのインストールは,Oracle Installerから行ないますが,このとき,ODBCドライバマネージャが古くなる点です.古くなったODBCドライバマネージャを新しいものに復活させるには,Visual Basic 5.0のCD-ROMのODBCディレクトリにあるSETUP.EXEを起動してMicrosoft ODBCセットアップで「再セットアップ」を実行します.
また,RDOを使うときに勘違いをして欲しくないのが.ファイルサーバー上に共有したMDBファイルはリモートデータではなくシステム的にはローカルファイルであり,RDOで接続すべき対象にはなり得ないということです.DAO/JetでのMDB排他問題などをクリアするためにRDOを使っても問題解決になりません.MDBを複数人数で更新するようなシステムを構築する解答としては,本誌97年7月号の私の記事にあるような独自3階層システムを構築するなどがあります.
Oracle Objects for OLE(oo4o)を使う
DAO/JetもRDOも駄目ならば,Visual BasicからOracleを使う方法はないのでしょうか.そんなことはありません.MicrosoftのSQL ServerにはMicrosoftのRDOがあるように,OracleのOracle7やOracle8にはOracleのoo4oがあります.oo4oは,Visual BasicとインプロセスOLEサーバー(Visual Basic 5.0からはActiveX DLL)の機能により接続します.また,そのインターフェイスは,DAO2.0とほぼ同じで,インターフェイスのみに注目すれば,RDOよりも余程DAOからの移行が行ないやすい仕様になっています.また,内部的にもODBCなどを使った多段階ミドルウェアではないので,ミドルウェア間のバージョンの整合なども気にする必要がありません.
oo4oを使うには(リスト10),以下の手順が必要です.
リスト10:oo4oの利用
Dim objSess As Object
Dim objDb As Object
Dim objDs As Object
Set objSess = CreateObject("OracleInProcServer.XOraSession")
Set objDb = objSession.DbOpenDatabase("vbm.world", "scott/tiger", 0&)
Set objDs = objDb.DbCreateDynaset("SELECT * FROM VbFaqPcdn", 8&)
Do While Not objDs .Eof
Debug.Print objDs ("FAQID").Value
objDs.DbMoveNext
Loop
Set objDs = Nothing
Set objDb = Nothing
Set objSess = Nothing
|
リスト11:oo4oの使い方(OraLogon.frm抜粋)
If pobjConn.LastServerErr = 0 Then
If pobjDb.LastServerErr = 0 Then
strErrText = Error$
Else
strErrText = pobjDb.LastServerErrText
End If
Else
strErrText = pobjConn.LastServerErrText
End If
Screen.MousePointer = vbDefault
pobjDb.LastServerErrReset
pobjConn.LastServerErrReset
|
最適なミドルウェアは?
Visual Basic 5.0とMicrosoft ODBC Driver for Oracleの組み合わせでは,動作しなかったり,性能もよくありませんでした.しかし,Visual Basic 5.0(SP2)とOracle ODBC Driverの組み合わせ,特にクライアントバッチカーソルを使ったときの性能は目を見張るものがあります(表3).これは,クライアントバッチカーソルがデータをRDBMSに反映するときに内部的にINSERTやUPDATEなどのSQL文を実行しているからだと思います.単純に速度だけならば,RDO2.0が最適なミドルウェアと言えるでしょう.しかし,サーバーカーソルだとVisual Basic 5.0自体が異常終了しますし,サンプルプログラムを動作させているときにクライアントバッチカーソルのAddNewが一度だけ異常終了しました.安定性という面では不安が残ります.
以上のことを考え合わせてみると,Oracle ODBC driverやMicrosoft ODBC Driver for Oracleの安定性が増すか,oo4oのパフォーマンスが向上しないと最適なミドルウェアが存在しないことになります.しかし,業務アプリケーションを提供する事を前提とするならば,少しでも安定した方を使うのがよいと思います.oo4oのパフォーマンスチューニングについては,本稿の最後に改めて述べることにしましょう.
表3:ミドルウェア別のパフォーマンス
| Server | Pentium200MHz (128MB) |
| WindowsNT 4.0 Server(SP3) | |
| Oracle8 Server Enterprise Edition R8.0.3(Final Beta) | |
| Client | IBM Thinkpad 535 (40MB) |
| Windows 95(OSR2) | |
| Visual Basic 5.0 (SP2) | |
| SQL*Net Client 2.3 | |
| Oracle ODBC Driver 2.0 | |
| Network | 10Mbps with SwitchingHub |
| OPEN | MoveLast | MoveNext | AddNew | Edit | Delete | |
|---|---|---|---|---|---|---|
| RDO2.0 ODBC Cursor | 2.014 | 1.190 | 3.365 | 29.837 | 238.391 | 228.869 |
| RDO2.0 Server Cursor | *1 | *1 | *1 | 30.116 | *1 | *1 |
| RDO2.0 Batch Cursor | 3.692 | 0.751 | 3.696 | 8.566 | 40.751 | 17.018 |
| DAO3.5 DAO/Jet | 0.097 | 0.403 | 21.411 | 70.508 | 237.356 | 241.360 |
| DAO3.5 ODBC Direct | 2.132 | 1.374 | 3.656 | *2 | *2 | *2 |
| Oracle7のパフォーマンスチェック機能 |
SQL TRACE
図11:TKPROF VIEWERサンプル
|
timed_statistics=true
と記述し,Oracle7を再起動します.そして,
ALTER SESSION SET SQL_TRAC=TRUE;
でトレースを開始して,
ALTER SESSION SET SQL_TRAC=FALSE;
でトレースを終了します.
トレース結果は,init[SID].oraのUSER_DUMP_DESTで指定されたディレクトリに,ORA_nnn.TRCのファイル名形式で保存されます.このTRCファイルをTKPROFユーティリティに入力すると図11のような出力結果が出力されます.なお,USER_DUMP_DESTは,サーバー上のディレクトリになるので,そのディレクトリを他の端末から共有できるように設定しておくと便利です.出力結果の各行は,
・Parse :解析
・Execute :実行
・Fetch :読み込み
の3つのフェーズを表わしています.また,各列は,
・count :回数
・cpu :CPU時間
・elapsed :経過時間
・disk :物理的に読み込んだブロック数
・query :一貫モード検索したバッファ数
・current :現行モード検索したバッファ数
・rows :SQL文で処理された行数
を表わします.
EXPLAIN PLAN
SQL TRACEが実際にDB上のデータを検索して結果を表示するのに対して,EXPLAIN PLANは,指定したSQL文を実行するためにOracle7が使う実行計画の各ステップを解析します.つまり,実データの投入前などであれば,EXPLAIN PLANを使って理論的にチューニングポイントを探すことになります.
EXPLAIN PLANを使うためには,事前に実行計画を格納するEXPLAIN表をチューニング担当のユーザーIDで作成する必要があります.UTLXPLAN.sqlというSQLスクリプトがサーバーのORANT\RDBMS73\ADMINにあるので,これを実行すれば必要な表が作成されます.EXPLAIN表が作成されていれば,EXPLAIN PLANは,次のような手順で使えます.
図12:EXPLAIN VIEWERサンプル
|
(1)EXPLAIN PLANを実行
EXPLAIN PLANの実行は,EXPLAIN PLAN文のパラメータとして該当するSQL文を指定して行ないます.
(2)PLAN_TABLEの内容表示
EXPLAIN PLAN文の実行によりPLAIN_TABLEに実行計画の解析結果が格納されるので,SQL文で取得します.
この手順を自動化するサンプルプログラムがリスト12です(図12).
Oracle7の実行計画は,もっとも効率的なアクセス方法を立案するOracleの内部処理で,その立案アルゴリズムには,RBO(ルールベースオプティマイザ)とCBO(コストベースオプティマイザ)があります.RBOはアクセス方法をランク1(ROWIDアクセス)からランク15(全件アクセス)にランク付けして,ランクの低い順番にアクセスパスを決定しますので,SQL文の書き方で同じ結果を得る時間が異なるときがあります.それに対してCBOは,たとえば検索条件を指定しても,テーブル全体に近いレコードを検索しなければいけないのならば(キー値の最少値と最大値から推論します),全件アクセスを行なうように実行計画を立案します.
リスト12:EXPLAIN VIEWER(EXPLAIN.frm抜粋)
Dim lngRet As Long
Dim strSQL As String
Dim objDs As Object
Dim strResult As String
On Error GoTo errEXPAIN:
'EXPLAIN PLANの実行
strSQL = "DELETE PLAN_TABLE WHERE STATEMENT_ID='XXX'"
lngRet = pobjDb.DbExecuteSQL(strSQL)
strSQL = "EXPLAIN PLAN SET STATEMENT_ID='XXX' INTO PLAN_TABLE FOR "
strSQL = strSQL & Trim$(txtSQL)
lngRet = pobjDb.DbExecuteSQL(strSQL)
'PLAN_TABLEの表示
strSQL = "SELECT DECODE(id,0,''," & _
"LPAD(' ',2*(LEVEL-1))||level||'.'||position)||' '||" & _
"operation||' '||options||' '||object_name||' '||" & _
"object_type||' '||" & _
"DECODE(id,0,'Cost='||position) QUERY_PLAN " & _
"FROM PLAN_TABLE " & _
"START WITH id=0 AND statement_id ='XXX' " & _
"CONNECT BY PRIOR id=parent_id AND statement_id='XXX'"
Set objDs = pobjDb.DbCreateDynaset(strSQL, 12&)
Do While Not objDs.EOF
strResult = strResult & objDs.fields(0).Value & vbCrLf
objDs.DbMoveNext
Loop
txtResults = strResult
exitEXPAIN:
On Error Resume Next
Set objDs = Nothing
Exit Sub
|
| Oracle7の主な特徴 |
さて,基本的な使い方とチェックの方法がわかったところで,Oracle7の特徴を把握しておきましょう.RDBMSベンダ最大手のひとつとして,業界標準とみなされる多くの機能がサポートされています.
行レベルロック
読み込み一貫性
読み込み一貫性は,実に単純なことを保証する機能ですが,その動作原理は「パフォーマンス向上」のために複雑な動作をします.そのため,その動作に目を向けすぎて機能を見失ってしまうときがあるようです.
読み込み一貫性の機能は,ある条件で読み込んだレコードは再検索するまで「サーバー上」に保管することです.この機能がないと,たとえば検索項目の値が変更されたときに読み込んだデータがどんどん変化してしまいます.この変更が通知さえされれば,一見便利なように見えますが,これでは,2つのプログラムがお互いに値を変えあうような状態になったときに収拾がつかなくなってしまいます.ですから,読み込み一貫性が保証されているのはきわめて重要なことなのです.そして,Oracleの特徴は,この必要不可欠な機能をいかにして効率よく実現しているかにあります.
読み込み一貫性の動作は,SGA上で更新の有無を管理し,更新されたデータの「更新前の値」をロールバックセグメントに保管し,そのことをSGAに記録します.これらの情報を元にして,それぞれのアプリケーションが読み込んだデータを確保します.素直に考えれば,更新前の値をそのままにして,ロールバックセグメントに「更新した値」を入れるような気がします.しかし,更新中のデータはコミット(そのまま更新)するのが普通の流れです.何らかの理由でロールバックする(更新前の値に戻す)方が稀ですから,「更新前の値」を別領域に確保する方がコミット処理が最適化されて,全体の速度が向上します.
データ整合性確保
正規化で分離したエンティティは,親エンティティに存在しないキーのデータが子エンティティに存在しないなどの整合性が確保される必要があります.この整合性をOracle7では,主キーと外部キー(FK)による参照整合性という機能で実現しています.
・親テーブルの更新:子テーブルが使っている主キー値は更新不可
・親テーブルの削除:子テーブルが使っている主キー値は削除不可
・子テーブルの挿入:親テーブルに存在しないコードを含むレコードは挿入不可
・子テーブルの更新:親テーブルに存在しないコードへの更新不可
また,ドメイン整合性といって,レコードの各項目にどのような値を設定できるかを制限する機能もあります.制限は,
・データ型による制約
・NULL値でないこと(NOT NULL制約)
・ある値であること(CHECK制約)
・列の値が重複しないこと(UNIQUE制約)
などです.
トリガ
トリガは,レコードの挿入前,挿入後,更新前,更新後,削除前と削除後のそれぞれのタイミングで処理を実行するように定義できる機能です.トリガはテーブルの変更に伴なって必ず発生しなければならない処理をPL/SQLで記述します.
分散データベース
分散データベースは,データを最も必要とするところにOracle7を導入し,その間を通信回線で結ぶことで,複数のOracle7をまとめてひとつの仮想的なデ―タベースとして構築する機能です.この機能を使えば,よく使うデータは手元のローカルデータベースへ格納し,あまり使わないデータ(または管理元が自部門ではないマスタデータ)は,リモートデータベースに格納するなどして,全体として通信回線の影響をあまり受けないシステムが構築できます.そして,Oracle7は,クライアントと直接接続しているデータベースとまったく同様にリモートデータベースを扱うことができるので,サーバーを分散しても,SQL文で複数のデータベースを同時に参照できます.分散データベースの指定は,
テーブル名@システム名
のように行ないます.このように簡単な指定でリモートデータベースを扱えるのは,Oracle7にシステム名に対応した接続プロトコルやアドレスを事前に登録しておけるからです.
しかし,常時接続できる通信回線が確保できるならば,無理にデータベースを分散しないで素直に1データベースでシステムを構築し,PL/SQLなどで通信速度の影響を受けない方向を検討した方が,運用が単純化できて手間のかからないシステムが構築できることが多いようです.
2フェーズコミット
分散データベースは,あくまでも仮想的なひとつのデータベースなので,同じ表が複数のデータベースに存在することはありません.この方式は,同時更新やデータの即時性(ある人がデータ更新を完了すれば,その直後であっても他の人がその更新データを参照できる)に優れています.しかし,データベース間の通信回線の速度がクライアント側の操作性に影響を及ぼしやすい方式でもあります.
2フェーズコミットは,他のデータベースで必要なデータについては,すべてのデータベースを同時に更新して,データ参照はすべてローカルデータベースで行なうようなシステム構築を手助けします(2フェーズコミットでは,データベースをノードという名前で管理します).2フェーズコミットはその名前の由来にもなっている,
(1)準備フェーズ
(2)コミットフェーズ
の2つのフェーズ(手順)を使って複数のリモートデータベースを更新します.まず,「準備フェーズ」ですべての関連ノードにコミットが可能かを問い合わせます.ここですべての関連ノードから「OK」が返ってきたら,「コミットフェーズ」で実コミットします.もし,「準備フェーズ」であるノードから「NG」が返却されてきたら,グローバルコーディネータ(ローカルデータベース)のノードも含めてすべてrollbackを発行します.
しかし,グローバルコーディネータがダウンしたときなどには,運用面でカバーする必要がありますので,2フェーズコミットの機能に必要以上に頼らない方がよいでしょう.1ノードで運用できるのならば,それに越したことはないでしょうし,また,分散しなければいけないような時も非同期レプリケーションを利用した方がよいでしょう.
レプリケーション
2フェーズコミットでは,関連ノードがすべて更新できないと更新に失敗します.そのため,即時にすべてのノードを更新できる反面,更新時に通信回線の速度や品質の影響を受けやすいという短所があります.この2フェーズコミットの長所短所を逆にしたものがレプリケーションです.レプリケーションを使えば,マスタ(更新元)側で指定した間隔で指定したテーブルの変更(前回反映時からの追加・更新・削除がその順番で記録されている)をレプリカ(指定先)に反映できます.反映時に通信回線でエラーが発生したときは,その回を無視して,その次の回に2回分の反映を行ないます.レプリケーションを使うときに注意することは,マスタを必ずデータの更新が発生する側にすることくらいです.
しかし,Oracle7 R7.3から追加された双方句レプリケーションを使うときには,もう少し注意することがあります.双方向レプリケーションは,双方がマスタでありレプリカであるので,同一レコードが複数ノードで更新される可能性があります.このような状態(コンフリクト状態)を解消するため,Oracle7では,コンフリクトが発生したレコードをどのように複写するかを取り決めた競合解消ルーチンを複数用意しているので,その中から業務にあわせて,最適なものを選択します.一般的にはタイムスタンプ値で競合を解消するのが基本になると思います.
パラレルクエリー
パラレルクエリーは,PCサーバーのように複数CPUが載っているマシンで有効な機能です.この機能を使うとSQL文での問合わせを分割してCPUごとに振り分けて同時並列処理を行ないます.ですから,複数CPUで十分なメモリを搭載したマシンをデータベースサーバーとして確保できれば,パラレルクエリーの利点を生かすことができます.逆に1CPUであったり,メモリが少ないマシンでは,問合わせの分割処理などのオーバーヘッドだけが増大し,通常の問合わせ方式の方がはやいこともあります.
パラレルサーバー
同じパラレルという言葉が使われているので,パラレルクエリーとパラレルサーバーはしばしば混同されて理解している人がいます.パラレルクエリーが1台のマシンの複数CPUを有効利用する方法なのに対して,パラレルサーバーは,複数台のマシンに共有ディスクを接続して同一データベースを使う方法です.
リスト13:ビットマップ索引の実行結果
|
ビットマップ索引
ビットマップ索引は,列の値が検索条件に一致するか否かをフラグ(0と1のビット値)として持って,そのフラブに対してANDやORを行なうことで効率的に検索を行ないます.ビットがコンピュータの最少情報単位ですので,ビットマップ索引をメモリ空間を有効に使えますし,ANDやORもコンピュータの基本演算なので非常に効率的に処理できます.
ビットマップ索引を使うときは,事前に
create bitmap index area_bit on 市コード(県コード);
として,「テーブル名(列名)」を指定したCREATE BITMAP文を実行しておく必要があります.このSQL文を実行しておけば,あとは,CBOが動くように設定するか,ALL_ROWSヒントなどをSQL文に埋め込めば,ビットマップ索引が採用されます.ビットマップ索引を使ったときの実行結果はリスト13のようになります.
リスト14:ハッシュ索引の実行結果
|
ハッシュ索引
ハッシュ索引とは,キーの値から直接レコード位置を計算する方式です.そのため,索引領域をデータベースに確保する必要がありません.ハッシュ索引を使うには,ビットマップ索引と同様にCBOが動作するように設定するかUSE HASE(テーブル名)ヒントをSQL文に埋め込みます.ハッシュ索引を使ったときの実行結果はリスト14のようになります.この例のように,必ずしもハッシュ索引を行なった方が速くなるとは限りません.ハッシュ索引を使ったときと使わなかったときの処理時間を実データを投入して比較してハッシュ索引を使うかを判断してください.
クラスタ化
設計時にきちんと表の正規化を行なうと同じようなキー項目を持ったテーブルが複数存在することになります.クラスタ化は,この同じキー項目をディスク上の同一ブロックに格納して効率よくデータを検索できるようにする格納方法です.つまり,正規化のところで出てきた「最適化」の対象になるテーブルに対してクラスタ化するとよいでしょう.ただし,通常のテーブル領域以外にクラスタ化した情報を格納する領域が必要ですので,ディスク容量を十分考慮してください.
パーティションビュー
データウェアハウスといって,簡単にいえば,ありとあらゆる情報をとっておいて,それを色々な角度から分析しようとする考え方があります.Oracle7は,このデータウェアハウスの格納場所としての使用に耐えられるようにパーティションビューという考え方をサポートしています.これは,顧客データなどを年ごとに別々の表に格納し,どの表がどの年のデータを格納しているかをビューが覚えておくことにとり,検索範囲外の表を検索にいかないという考え方です.ですから,データが何年分蓄積されようとも検索範囲が同じならば,いつでも同じ(毎年同じデータ量ならば)検索時間で結果を取得できます.
ヒストグラム
R7.2までのCBOでは,各項目の最大値,最小値,カーディナリティしか収集できませんでした.ヒストグラム(お手元にExcelがあるときは,ヘルプで「ヒストグラム」を検索するとそこに詳しく説明されています)を使うことで,その他にデータの分散度が収集できるので,ばらつきが大きいデータに対しても,適切な実行計画をオプティマイザが選択できるようになりました.
なお,収集したヒストグラムのデータは,USER_HISTOGRAMSビューで参照できます.
スタークエリーの高速化
正規化のところで登場した第三正規化は,データの冗長性を排除することと引き換えに表の結合数を増加させてしまいます.そのため,性能向上のために設計段階で正規化したものを元に戻すときがあります.Oracle7ではこの結合を効率的に処理する方法を導入することで,正規化を崩す作業を行なわなくても済むようになりました.それが,スタークエリーの高速化です.この名前の由来は,ひとつの表の周りに小さなマスタ表が連結された姿が☆型に見えることから来ています.
更新可能な結合ビュー
更新可能な結合ビューもスタークエリーの高速化同様,モデリング結果を素直に実テーブルに定義するための機能です.この機能のおかげで同一主キーの表をひとつにまとめるなどの最適化を行なう必要がなくなりました.
PL/SQL
PL/SQLというサーバー上で動作する言語があることもOracle7の特徴のひとつです.しかし,SQL ServerのTransact-SQL同様メーカー独自な言語なので,習得が難しいという欠点がありました.しかし,Oracleは将来的にはPL/SQLの役目をJAVAにすることを公表しています.JAVAが実装されればPL/SQLのニーズはなくなっていくと思いますが,Oracle8 R8.0でもまだ実装されていないので,あとしばらくはPL/SQLを使うことになります.ただ,方向性としてOracleは,JAVAとの関係を深めているので,これを機会にJAVAの勉強を開始するのもよいかもしれません.このときは,Microsoft J++などの方言は使わずに100%PureJAVAの言語を使ってください.JAVAには,デファクトスタンダードがない状態ですので,仕様的にスタンダードに近いものを使って変な癖がつかないように注意してください.
Oracle Enterprise Manager
Oracle Enterprise Managerは,Oracleの統合管理ツールです.近頃の流行のリポジトリで複数のOracle7 Serverを管理することができます.面白いのは,このリポジトリを格納するのにOracle7が必要なことで,管理対象に管理データを格納することになります.耐障害性を高めるためにも,PO7などを別途購入して,PO7上にリポジトリを格納する方が良いかもしれません.
また,Oracle8では,Oracle Enterprise Managerのツール群がJAVA化されています.
テーブル領域管理 ―エクステントの監視―
Oracle7は,テーブルや索引をエクステントと呼ばれる単位で管理し,新たな領域が必要になると動的に領域拡張します.しかし,領域拡張を繰り返すと1テーブルのデータがディスクの様々な位置に格納され処理効率が低下します(この状態をフラグメンテーションといいます).そのため,エクステントの状態を監視して,フラグメンテーションを解消すれば,常に最良の状態にデータベースを維持することができます.エクステントの状態を監視するには,静的データディクショナリビューのUSER_SEGMENTSビューを使います(図13,リスト15).USER_SEGMENTSビューのextentsフィールドの値が5を超えるものは,エクステント拡張を起こしすぎているので1個の連続領域にまとめた方がよいでしょう.
リスト15:Extent Viewer(EXTENT.frm抜粋)
lvwExtent.ListItems.Clear
strSQL = "SELECT segment_name,segment_type,bytes/1024||'KB' kbytes,
"extents,max_extents " & _
"FROM user_segments " & _
"ORDER BY extents desc"
Set objDs = pobjDb.DbCreateDynaset(strSQL, 12&)
Set objField(0) = objDs.fields(0)
Set objField(1) = objDs.fields(1)
Set objField(2) = objDs.fields(2)
Set objField(3) = objDs.fields(3)
Set objField(4) = objDs.fields(4)
Do While Not objDs.EOF
Set itmList = lvwExtent.ListItems.Add()
itmList.Text = objField(0)
itmList.SubItems(1) = objField(1)
itmList.SubItems(2) = objField(2)
itmList.SubItems(3) = objField(3)
itmList.SubItems(4) = IIf(objField(4) = _
"2147483645", "UNLIMITED", objField(4))
Set itmList = Nothing
objDs.DbMoveNext
Loop
exitTreeMake:
On Error Resume Next
Set objField(4) = Nothing
Set objField(3) = Nothing
Set objField(2) = Nothing
Set objField(1) = Nothing
Set objField(0) = Nothing
Set objDs = Nothing
Me.MousePointer = vbDefault
Exit Sub
|
エステントをひとつにまとめるには
(1)テーブルのエクスポート
(2)テーブルの削除
(3)テーブルのインポート
を行ないます.
動的パフォーマンス(V$)表
また,Oracle7には,システムのパフォーマンスに関する情報が格納されている動的パフォーマンス表があります.アプリケーションを開発するときに,この動的パフォーマンス表を意識することはないでしょうし,意識しなければならないようなシステム要件やシステム仕様は,そのような要件や仕様なりをきちんと解釈したり,システム全体として本当に必要かどうか再考すれば,大抵はなくなるはずです.これは,Visual BasicでWindows APIを使うことにも共通することです.しかし,私はこの動的パフォーマンス表が気に入っています.それは,システム要件やシステム仕様と離れた部分で,プラスαの提供機能として利用するとかなり面白いことができるからです.
たとえば,V$SESSIONビューを使って(リスト16)現在ログオンしているユーザーの一覧を簡単に取得できます(図14).
リスト16:ログオン中ユーザーの表示
column username format a10 trunc heading "USERNAME" column lockwait format a10 trunc heading "LOCK" column machine format a16 trunc heading "MACHINE" column terminal heading "TERMINAL" column program heading "PROGRAM" SELECT username,lockwait,machine,terminal,program FROM V$SESSION ORDER BY username; |
| 3階層システムの構築 |
Oracle7にはPL/SQLがあるのでビジネスロジックをRDBMS上に格納して,クライアント側のロジックを絞り込んだthinクライアント型の2階層システムが比較的簡単に作成できます.しかし,サーバー側の資源が乏しいなどの理由で大規模なストアドプロシージャを組み込めないときは,Remote OLEやDCOMを使って3階層システムを構築することができます.しかし,RemoteOLEにしてもDCOMにしてもレジストリ管理などが煩雑で,手軽に業務アプリケーションに適用することが難しいのが現状です.そこで,DCOMの基本プロトコルであるUDP/IPプロトコルのみを使って独自プロトコルを作り,3階層システムを構築するのもひとつの手だと思います.
UDP/IP 3階層システム
ActiveX Documentsとの併用
UDP/IP 3階層システムのクライアント側をActiveX Documents化することによりモジュールの配布の手間を省くことも可能です.社外のWebサイトからActiveXコントロールやActiveX Documentsのダウンロードはウィルスや悪意あるプログラムの進入防止の点でお勧めできませんが,社内のサーバーからダウンロードすることは何の問題もないでしょう.そして,IE4.0ではインターネットゾーンやイントラネットゾーンというようにゾーンを分けて,ゾーンごとにセキュリティレベルを設定できるようになりますので,間違えてインターネットから危険なActiveXコントロールをダウンロードする心配が軽減されます.ですから,これからは,イントラネットからしかActiveXコントロールやActiveX Documentsをダウンロードしない傾向が強まると思いますし,そうでなければ,この2つのActiveX技術を安心してアプリケーション開発に使うことはできません.
図15:Oracle3階層システム
|
ActiveX Documents化には,ActiveX Documents Migration Wizardを使えば比較的簡単にできそうですが,ユーザードキュメント名が8文字を超えているとき(VBDファイル名が8.3形式にならないとき)は,ダウンロードに失敗するなどゼロからActiveX Documentsとして作成したときと動作が異なるときがあるので注意が必要です.Wizardを信用せずに,画面デザインについては,ゼロからActiveX Documentsとして作成し,Wizardで返還したロジックをカットアンドペーストでコピーするのが得策かもしれません.その方法で作った3階層システムを図15に示します.
| oo4oパフォーマンスチューニング |
それではまとめとして,ここまでに解説したOracle7の特徴を踏まえてoo4oのパフォーマンスを向上させる方法をご紹介しておきましょう.
オブジェクト参照を減らす
図16:オブジェクト参照チューニング
SQL文を使う
RDO2.0のクライアントバッチカーソルは,更新時にINSERTやUPDATEのSQL文を実行します.oo4oでもReadOnlyでSELECT文を実行して,更新時はINSERTやUPDATEのSQL文を実行するようにロジックを変更すれば,パフォーマンスが向上します.
ホスト変数を使う
DAOやRDOでは不可能な機能にホスト変数の利用があります.Oracle7は,まったく同じ文字列のSQL文を連続して受け取ると,2回目以降はSQL文の実行がはやくなります.この利点を最大限に利用するのがホスト変数です.つまり,SQL文には,変数名を記述して,その変数に対して別の方法で値を設定・取得します(図17).もちろん,oo4oはこのホスト変数に対応しています.
ホスト変数は,いわゆるセション単位のグローバル変数になりますので,複数のSQLで同じ変数名を使っていれば,値を変更しない限り,同じ値としてSQL文が処理されます.
また,ホスト変数を拡張した「PL/SQL表」という配列もサポートしていますので,複数レコードのまとめ読みや,まとめ書き(RDO2.0のバッチカーソルに近いイメージです)が可能です(リスト17).
リスト17:PL/SQL表(OraOo4o.frm抜粋)
pobjDb.Parameters.AddTable "intItem", 1, 1, 1000, 8
Set objSpread = pobjDb.Parameters("intItem")
For iintIndex = 1 To pcMaxCnt
objSpread.put_Value iintIndex, (iintIndex - 1)
Next
strSQL = "BEGIN pkgTEST.subTEST1(:intItem," & pcMaxCnt & "); END;"
pobjDb.DbExecuteSQL (strSQL)
|
PL/SQLを使う
図17:ホスト変数チューニング
SQL文は非手続き型の言語なので,本来条件分岐構造やループ構造がありません.しかし,それではどうしても柔軟なプログラムを作ることができません.OracleがSQL文を独自に拡張したPL/SQLをOracle7に搭載していることは前述のとおりですが,このPL/SQLを使えば,今までVisual Basic側で実行していたループや条件分岐などをOracle7上で実行できます.そのため,SQL文の発行回数が激減して,比較的速度の遅い回線を経由しても実用的な応答速度を確保できます(図18).
図18:PL/SQL化チューニング
ちなみにPL/SQLは,Procedure Language Extensions SQL(SQLへの手続き型言語拡張)の略称であり,OracleがAdaを元にして拡張しています.Adaは,Pascalを大規模アプリケーション作成のために拡張した言語で,データ抽象や情報隠蔽などに重点を置いたプログラム言語なのです.
| Oracle8来日 |
本号が発売されるころには,Oracle8 Server Enterprise Edition R8.0に引き続き,Oracle8 Server R8.0も発売されていると思います.そして,まもなくPersonal Oracle8 R8.0も発売され,Oracle8シリーズが全製品揃います.
Oracle7で稼動しているシステムを早急にOracle8に以降する必要はないと思いますが(Oracle7は,R7.4が最終リリースになるそうです),これから開発するものはOracle8を選択した方がよいでしょう.Oracle8はOracle7の上位互換となっていますので,あたかも速度が速くなったOracle7とみなして開発することができます.また,現時点ではOracle8シリーズの特徴のひとつであるオブジェクト型などに対応したCASEツールなどの周辺環境が整っていないので,Oracle8をOracle8として使うよりもOracle7として使ったシステム構築を考慮した方がいいでしょう.つまり,Oracle Disgner/2000 R1.4とOracle Developer/2000 R1.5の次版が発売されるまでは,Oracle8のOracle7互換部分のみを使うのがよいと思います.
ただ,現在Oracle7 WGS R7.3でパラレルクエリーを使っているときは,Oracle8 Server R8.0では,Oracle8 Server EEとの差別化のために,この機能が削られているので注意が必要です.
| 最後に |
本稿を執筆するにあたり,「RDBMSの設計工程」に関してご協力頂いた吉野未亜さんにこの場を借りて感謝します.
サンプルプログラム収納ディレクトリの解説\APS:3階層システムサンプル(VB5Only) \AXDOC:ActiveX Documents \UDPMW:UDP Protocol Server \EXE:UDP Protocol Client \BENCH:Oracle接続ベンチマーク(VB5Only) \OO4O:oo4o手法別ベンチ \VB5:DAO/RDO/oo4oベンチマーク \EXPLAIN:EXPLAIN VIEWER \VB4:Visual Basic 4.0用 \VB5:Visual Basic 5.0用 \EXTENT:EXTENT VIEWER \VB4:Visual Basic 4.0用 \VB5:Visual Basic 5.0用 \TRACE:TKPROF VIEWER \VB4:Visual Basic 4.0用 \VB5:Visual Basic 5.0用 [サンプルプログラムを動作させる前に] 1:SQL*Net V2.xのセットアップ SQL*Net EasyConfigrationでデータベース別名「VBM」を作成してください ODBC32のセットアップ(Oracle ODBC Driver 2.0を選択してください) 2:データソース名「VBM」,接続文字列「VBM」