受発注システムで体験するオブジェクトデータベース
問い合わせ処理の実装
次に、オブジェクト指向プログラミングで、なんらかの問い合わせ処理を行うケースについて考えましょう。
こんな処理が現実に必要かどうかはさておき、以下では注文明細の項目に指定した色のものが含まれる注文を検索し、リストして、その中から注文を選んで、注文書を表示するというプログラミングです(後半は、前例とほぼ同じ処理になります)。
OrderPrint2() { Read "色 ?",color Set query = ##class(%ResultSet).%New("%DynamicQuery:SQL") Do query.Prepare("SELECT DISTINCT TheOrder->ID AS OID FROM Sample.OrderItem WHERE TheProductStock->Color = ?") Do query.Execute(color) Write "Order ID",! While (query.Next()) { Set oid=query.Get("OID") Write oid,! } Read "enter OID ",oid Set ord=##class(Sample.Order).%OpenId(oid) Write !,?30,"注文明細書",! Write "注文番号 ",oid,! Write "〒",ord.Customer1.Address1.Zip," ",ord.Customer1.Address1.Pref,ord.Customer1.Address1.City,ord.Customer1.Address1.Street,! Write "電話番号 ",ord.Customer1.Telno,! Write ord.Customer1.Name," 御中",! Write ! Write "商品名",?30,"サイズ",?45," 色",?55,"数量",?60,"金額",! Write "--------------------------------------------------------------------",! For i = 1 : 1: ord.Items.Count() { Write ord.Items.GetAt(i).TheProductStock.TheProductSize.TheProduct.Name Write ?30,$J(ord.Items.GetAt(i).TheProductStock.TheProductSize.SSize,4) Write ?45,$J(ord.Items.GetAt(i).TheProductStock.Color,6) Write ?55,$J(ord.Items.GetAt(i).Quantity,4) Write ?60,$J($FN(ord.Items.GetAt(i).TheProductStock.TheProductSize.Price*ord.Items.GetAt(i).Quantity,","),8) Write ! } Write "--------------------------------------------------------------------",! Write "合計",?60,$J($FN(ord.Total,","),8) }
Cachéでは、問い合わせ処理には、SQLを使います。ただし、SQLといってもオブジェクト指向風の味付けがしてあります。
SQLを記述するときに、オブジェクト参照と同様にカスケード参照ができるとなにかと便利です。その最大のメリットは、結合のための追加の条件記述が必要ない点です。
Caché SQLのカスケード参照には、->を使います。SQLでは、.は別の意味ですでに使われていますので、この用途には使用できません。上の処理で使われている以下のSQL文の意味を考えてみましょう。
SELECT DISTINCT TheOrder->ID AS OID FROM Sample.OrderItem WHERE TheProductStock->Color = ?
これは、Sample.OrderItemテーブルのTheProductStockカラムが指すProductStockテーブルの色が、パラメータで指定された値に一致するSample.OrderItemレコードを取得して(複数行)そのレコード単位にTheOrderカラムが指すOrderテーブルのIDを取得する、という処理になります。これを一般的なSQLで表現すると、3つのテーブル(Sample.OrderItem、Sample.ProductStock、Sample.Order)の結合処理になります。
Caché SQLの->は、暗黙結合と呼ばれます。暗黙結合を使うとSQL文が非常にすっきり記述できると感じませんか?
ここでも示したように、現実のアプリケーションでは、なんらかの問い合わせ処理で処理対象を絞って、その個々の処理対象に対して処理を進めていくというスタイルが一般的だと思われます。従って、オブジェクト指向データベースプログラミングといっても、オブジェクト参照だけでことが足りるわけではなく、なんらかの問い合わせ言語の処理が含まれます。
Cachéの場合は、この問い合わせ用にフルセットのSQLを用意し、かつオブジェクト指向風な拡張がなされています。
メモリにロードされるタイミングは
以上で、オブジェクト指向データベースを使ったアプリケーション構築のエッセンスの説明は終わりです。ここで、高度な性能を要求されるデータベースアプリケーション構築の経験のある方は、1つの疑問を持たれることと思います。
今回の例題は、1つの注文を表示する処理ですので、容量的にはたかがしれていますが、もし大量の関連オブジェクトがひも付いているオブジェクトを処理する必要がある場合に、それらの関連オブジェクトは、どのタイミングでプログラム上のメモリにロードされるのでしょうか?
これは、RDBを使って、オブジェクトモデルを構築する場合にも考慮すべき問題です。1つの実装パターンとしては、最初に必要なSQLを連続で発行して、あらかじめ後の処理に必要なオブジェクトモデルを事前に構築する方法が考えられます。
この方法は、今回の例題を処理するには、何の問題もない方法ですが、仮に注文明細が1万を超えるように大量に存在する場合には、処理時間、メモリ使用量など問題になってきます。その場合は、1行づつフェッチしながら処理を進めていく必要があり、その部分の処理が煩雑になるでしょう。
再度例題プログラムを眺めてみましょう。一見すると、データベースからオブジェクトの実体を取得している可能性のある処理は、OpenId()メソッドしかないように見えます。
それでは、このOpenId()を実行した時点で注文オブジェクトとそれに関連するそのほかのオブジェクトの実体すべてをプログラムのメモリ上にロードするのでしょうか? この例題の場合には、それでも問題ないでしょうが、関連するオブジェクトが100万存在すると、おそらくメモリが足らなくなるでしょう。同時に処理時間もかかることでしょう。
実は、関連オブジェクトに関しては、参照が発生した時点にロードされます。具体的にはカスケード参照されたオブジェクトがメモリに展開されていないことを検知した場合に、データベースからそのインスタンスをメモリにロードします。この一連の操作をCachéではスィズリングと呼びます。スィズル(Swizzle)とは、飲み物をかき混ぜるスティックという意味があるそうです。徐々に浸透していくという意味で使われているのだと思います。O/Rマッパーなどでも同等の機能があり、それはレイジーロード(怠け者のロード)と呼ぶのが一般的なようです。Cachéはこのスィズリングにより、大量関連オブジェクトのロードの問題を回避しています。
難しいことはデータベースで。だからプログラマは集中できる
オブジェクトデータベースを使うことにより、裏方の難しいことはデータベースシステムが面倒を見てくれて、開発者はビジネスロジックに集中できます。この裏方の難しい仕事のでき具合は、アプリケーションの性能に大きく影響します。
O/Rマッパー使うとオブジェクトデータベースと同様にプログラマーの仕事は、大分軽減されます。しかし、内部でSQLに逐一変換しなければならないという制約上、性能の向上には限界があります。これが、O/Rマッパーがなかなか普及しない1つの要因ではないかと思います。
佐藤 比呂志(さとうひろし)
大手SI、先進的企業のIT部門にて、大規模開発プロジェクトに従事後、米国大手ソフトウェア会社にてソフトウェア製品開発マネージャを務めた後、1996年より仕様策定、共同開発などでCachéの日本対応に尽力。
その後、同製品のプロダクトマネージャに。2001年インターシステムズコーポレーション入社。2003年インターシステムズジャパン株式会社設立と同時に転籍。テクニカルコンサルティング部・教育サービス部部長。
現在、ITmedia オルタナティブ・ブログにて「隠れた財産」を執筆中。
3/3 |
Index | |
受発注システムで体験するオブジェクトデータベース | |
Page 1 データモデルの構築 Cacheでのプログラミング実例 |
|
Page 2 プログラマによって差が出ない記法 RDBではどう表現されるか |
|
Page 3 問い合わせ処理の実装 メモリにロードされるタイミングは 難しいことはデータベースで。だからプログラマは集中できる |
いま知るべきオブジェクトデータベースの世界 |
- Oracleライセンス「SE2」検証 CPUスレッド数制限はどんな仕組みで制御されるのか (2017/7/26)
データベース管理システムの運用でトラブルが発生したらどうするか。DBサポートスペシャリストが現場目線の解決Tipsをお届けします。今回は、Oracle SE2の「CPUスレッド数制限」がどんな仕組みで行われるのかを検証します - ドメイン参加後、SQL Serverが起動しなくなった (2017/7/24)
本連載では、「SQL Server」で発生するトラブルを「どんな方法で」「どのように」解決していくか、正しい対処のためのノウハウを紹介します。今回は、「ドメイン参加後にSQL Serverが起動しなくなった場合の対処方法」を解説します - さらに高度なSQL実行計画の取得」のために理解しておくべきこと (2017/7/21)
日本オラクルのデータベーススペシャリストが「DBAがすぐ実践できる即効テクニック」を紹介する本連載。今回は「より高度なSQL実行計画を取得するために、理解しておいてほしいこと」を解説します - データベースセキュリティが「各種ガイドライン」に記載され始めている事実 (2017/7/20)
本連載では、「データベースセキュリティに必要な対策」を学び、DBMSでの「具体的な実装方法」や「Tips」などを紹介していきます。今回は、「各種ガイドラインが示すコンプライアンス要件に、データベースのセキュリティはどのように記載されているのか」を解説します
|
|