2014年6月30日月曜日

MS Access を使った大規模な開発のリスク

Microsoft Accessで大規模なデータベースを構築するのは無茶ですが、コストに負けて採用してしまうことはある。それでも MS Access を使うことになった場合は、以下のことに気を付けるべきです。

1.データサイズ

Access の仕様として公開されている制限があります。
  • Access データベース (.accdb) ファイルのサイズは 2GB
  • テーブルのサイズも 2GB
Access 2010 の仕様
http://office.microsoft.com/ja-jp/access-help/HA010341462.aspx

運用中に 2GB に到達してしまうと、データベースファイルはほぼ確実に破損します。ファイルを分割すれば、ファイルサイズの制限は解決できるかもしれませんが、テーブルサイズの制限を超過してしまう場合は、テーブルを分割して解決できるでしょうか?

じつは仕様書には書かれていない制限もいくつかあります。例えば、
  • クエリ結果のサイズ(下記を参照)
  • 連続で開く処理と閉じる処理を行うと、データファイルが破損する。(下記を参照)
これ以外にも MS Accessで大量のデータを扱うには以下の懸念があります。
  • オプティマイザー、統計情報が貧弱
  • 最適な実行計画に誘導することができない
  • SQLチューニングのツールが無い
また分割したテーブルを UNION 統合する必要があるならば検索時間は長くなり、大量のデータで処理回数が増加すれば処理が終わらないという問題が出てきます。テーブルのサイズ上限は Access の採用可否の判断材料とすべきです。

2.クエリサイズ

エラーメッセージ:「3183 DAO.Database クエリを完了できません。クエリ結果のサイズがデータベースの最大サイズ (2GB) より大きいか、クエリ結果を一時的に保存するディスクの空き容量が不足しています。」

クエリの仕様として Accessの仕様書にも書くべきだと思うが、クエリにも制限があります。さらに「クエリ結果のサイズ」が指すものが曖昧で、出力結果のサイズでもあり、内部の一時領域でもある様子です。内部的にはどういう実行計画になるか分からないので、この制限を意識するデータ量になるならば、Access の採用可否の判断材料とすべきです。

3.連続で開く処理と閉じる処理を行うと、データファイルが破損する

これ言い換えると、「繰り返しのベースとなるレコードが 40,000 件を超えており、データファイルが分割されているため処理毎に接続を切り替えるとデータファイルが破損する。」これも 40,000件 をAccess の採用可否の判断材料としたほうが無難です、理由は下記に挙げるように想定外の問題が多いため。

http://support.microsoft.com/kb/283849
Access 2002 以降の破損したデータベースをトラブルシューティングおよび修復する方法
ループ処理の中で、開く処理と閉じる処理を大量に行うことを避けます (40,000 回を超えて、連続で開く処理と閉じる処理を行うと破損する場合があります)。


この対策としては、接続したままにする手段がある。
  • リンクテーブルを開いたままにする
  • DAO.DBEngine.OpenDatabaseでデータベースを開いたままにする

http://office.microsoft.com/ja-jp/access-help/HP005187453.aspx
Access データベースのパフォーマンスを向上させる
リンクしたデータベースを開いたままにしておくと、メイン データベース、テーブル、およびフォームを開く際のパフォーマンスが向上します。(中略)また、関連する .ldb ファイルの作成や削除を防ぐこともできます。


ただしリンクテーブルとDAO.DBEngine.OpenDatabase は接続が衝突する。
エラーメッセージ:「3734 DAO.Workspace マシン 'localhost' のユーザ 'Admin' がデータベースを開けない状態、またはロックできない状態にしています。」

それに繰り返し回数が少なくても、必ずしも安全ではないのは以下の通り。
エラーメッセージ:「3051 DAO.Database ファイル 'C:\work\Sample.laccdb' を開くか、書き込むことができませんでした。他のユーザが排他的に開いているか、データの表示と書き込みを行う権限がありません。」
排他モードでなくともシングルユーザでの接続を繰り返すと発生する可能性がある。ロックファイル(laccdb)のオーバーヘッドは無視できないと考えたほうが良い。データベースを同時に使用できるユーザーの数は 255 まで可能である仕様なのは本当なのだろうか?