「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
どのOSも(WindowsもLinuxも)バイト・ストリームによる
程度はサポートしています。
- 汎用コンピュータ(メインフレーム)や一部のオフコンの専用OSでは、
各ファイル(データセット)内の、レコードの属性を定義する。
(固定長/可変長/非定型、固定長の場合のレコード長、格納・検索方法など)
- なお、いわゆるオープンシステムではバイトストリームが基本であり、
ファイル編成法は存在しない(詳細は「レガシーシステムとオープンシステムの比較」を参照)。
本ページでは、これら(ファイルシステム)を使用しての、大量データの処理方式を考えます。
- なお、メモリに保持可能なデータ量の場合の設計ディシジョンについては考慮しません。
この場合、メモリの大量消費による同時実行性の低下やCPU時間が問題となります。
アクセス方式とレコード長 †
SAM(順次アクセス方式) - シーケンシャル・アクセス †
- SAM(順次アクセス方式) - シーケンシャル・アクセスを
実現するにあたっては、特に問題となる点はありません。
- READやWRITEのAPIによって自動的に
ファイル・ポインタ(読み書きの開始点)が移動されます。
DAM(直接アクセス方式) - ランダム・アクセス †
DAM(直接アクセス方式) - ランダム・アクセスを実現するにあたっては、
特にファイル・ポインタ(読み書きの開始点)の制御が問題となります。
固定長 †
固定長レコードの場合、
- ファイル・ポインタ(読み書きの開始点)の制御が容易です。
- Windowsでは、SetFilePointer?関数を使用して、
ファイル・ポインタ(読み書きの開始点)を、全て自分で制御して
ランダム・アクセスを実現する必要があります。
- 4GB(32ビット)以上のファイルを扱う時は、
上位32ビットと、下位32ビットを64ビットデータ型に変換する必要があることでする。
- このため、レガシーVBではSEEKステートメントで2GB以上の
ファイル・ポインタを指定することができないという制約があります。
4GB(32ビット)でないのは、signedの型を使用しているためと思われます。
- .NETでは、FileStream?.Seek メソッドの引数が
64bit(long型)対応されたため、この問題は発生しなくなったようです。
余談になりますが、.NETで固定長レコードを処理する場合に便利な
C構造体によるバッファ型抜きを.NET構造体とMarshalクラスを使用して実現できます。
なお、このバッファ型抜き処理は、Open棟梁の共通部品に実装されています。
可変長 †
可変長レコードの場合、
- ファイル・ポインタ(読み書きの開始点)の制御が困難です。
- 理由は、簡単でレコード長が可変のためn番目のレコードの
ファイル・ポインタ(読み書きの開始点)ができないためです。
- SAM(順次アクセス方式) - シーケンシャル・アクセスで、
事前に、全てのデータを読み取っておき、これにより、
全てのレコードの開始位置を配列などに記憶しておく。
- 初回の開始位置の配列作成の読み込みにI/O時間がかかってしまう。
- 全てのレコードを読み取ることが困難な場合でも、
レコード番号などがデータ中に含まれるようなら
ファイル・ポインタ(読み書きの開始点)を推測して、
効率良くレコードにアクセスする事を試みるのは可能。
- レコード番号などがデータ中に含まれる必要がある
カスタム仕様であるため、汎用品は存在しない。
- 可変長レコードの主要なフォーマットにはCSVがあります。
- CSVの問題は、CSVのフォーマットの仕様によってパーサが複雑になる事です。
- 例えば、データ内に改行コードなどが含まれる場合は、
前述のファイル・ポインタ(読み書きの開始点)推測して、
レコードにアクセスする等の方式の採用は困難です。
- ただし、1フィールドの最大データ長が決まっていれば、可能と言えば可能です。
- このため、以下のどちらの方式を採用したとしても、
- 全てのデータを読み取っておき、全てのレコードの開始位置を配列などに記憶しておく。
- ファイル・ポインタ(読み書きの開始点)を推測して、効率良くレコードにアクセスする。
- ※ FileStream?.Seek、Positionと、StreamReader?.ReadLine?を併用する。
- 結局の所、CSVパーサーの高速化が必要になるようです。
- .NETには、VB 2005用の機能として、CSVパーサーが準備されているようです。
しかし、APIの使用からも、ランダム・アクセスはサポートされていないようです。
- ファイル編成法のないオープンシステムの
バイト・ストリームのファイルシステムでは
可変長レコード・ファイルのレコード更新処理は不可能。
- 固定長レコードの処理と同じように、
C構造体によるバッファ型抜きでの処理することが不可能。
実装上の考慮点 †
更新処理 †
固定長レコードの更新処理以外は、
- 可変長レコードの更新処理(レコード長が変わる更新)
- テキスト・ファイルの中間に文字やパラグラフを挿入する。
- .etc
更新差分情報のみをメモリに保持して、
最終的に全てのデータをバイト・ストリームで書き出し直す必要がある。
このため、I/Oのオーバヘッドが非常に大きくなってしまいます。
MMFの使用ポイント †
メモリマップトファイル(MMF)を使用すれば、
- マップビューのマップ・アンマップによるランダム・アクセス
- マップビューの範囲でオンメモリ処理(I/O回数の軽減)
が可能になり、効率的に参照処理を
実装できるようになる可能性があります。
余談 †
COBOL+VSAM †
- COBOLなどは、RDBMSが無い時代に、ホスト・UNIXのOSに実装される
VSAMを内部的に使用して業務アプリケーションを開発することを
目的としていたため、この仕組みに適合した言語仕様になっている。
- このため可変長のランダム・アクセスであっても
実装が容易で、このような問題は発生しないようです。
このため、昔は良く「Windowsはファイル・システムが弱い」と言われていました。
Unix、LinuxとWindowsのFS †
Unix、Linuxのファイルシステムでは断片化が発生し難いと言う話があったので、
簡単に技術的な背景を纏めているサイトをリンクしました。
DBを使用する場合 †
RDBMS+SQLを使用することによって、
アプリケーションはデータ・アクセスの際に
- ファイル編成法(固定長/可変長/非定型、格納・検索方法)と
- 上記に対応するアクセス方法(APIの利用方法)
を考慮せずに、論理データに直接アクセスできるようになりました。
バッチ処理 †
大量データのバッチ処理は、基本的にストアドが高速です。
- ネットワークやプロセス間の通信処理が発生しないので、
データ送受信のラウンドトリップが発生しない。
- カーソルによるフェッチが使用できるため
大量データの結果セットを取得した場合も
メモリ消費量を抑えることができる。
Java、.NETで実装する場合は、性能的に
問題が無いかを事前に検証した方が良いでしょう。
検索、結合、統合、集計機能 †
大量データのバッチ処理で、
以下の様なDBMSの機構を使用したいケースもある。
- 検索機能(Index Seek)
- 結合、統合、集計機能(Join、Union、Group By)
検索や結合機構にはインデックスが使用されているため
- インデックスの構築・更新
- 統計情報更新の構築・更新
等が必要になる。
オーバーヘッド †
DBを利用可能にするまでのオーバーヘッドには以下のものがあります。
- インポート(インサート)
- インデックス構築・更新
- 統計情報の構築・更新
- 必要であればエクスポート
無償で利用できるDB †
- MDB(accdb)、インストール不要で運用も楽。
- SQL Server Express Edition
補足 †
しかし、バッチ処理等で高性能なデータ変換処理を要求されるケースでは
未だにファイル・レベルでのデータ処理が必要になることもあります。
例:データのエクスポート → 変換処理(シーケンシャル) → データのインポート
ETLツールを導入する方式 †
HULFT DataMagic?などを使用することで
可変長レコードの大量データも容易に処理できる可能性があります。
Tags: :データアクセス