FileMakerを使用したアプリケーションの構築に不可欠な「計算フィールド」と「集計フィールド」。計算フィールドではビルトインの関数を使いこなし、簡単なものから複雑なものまで自由に数式を組み、簡単に計算結果を得ることができる。集計フィールドも簡単な操作で合計・平均値・標準偏差・合計に対する比といったさまざまな切り口で集計結果を算出する事が可能だ。FileMakerの開発において、工数を縮める一つのキーと言っても過言ではないだろう。

たいへん便利なこの2タイプのフィールドだが、Webアプリケーションではこれらのフィールドの取り扱いを間違えると大幅な性能低下の原因となる、要注意のフィールドだ。本稿では2回にわけて、これらのフィールドを使う事での性能低下と、性能低下を回避する実装手段を紹介しよう。1回目はおもに「計算フィールド」について取りあげる。

非保存の計算フィールドで検索をおこなうことでのスピード低下

やや規模の大きいアプリケーションをFileMakerで作成したことのあるデベロッパならすでにおわかりかと思うが、計算・集計フィールドはレコード数が多ければ多いほど、動作スピードが鈍化する。とくに計算フィールドにおいては、リレーションシップフィールド(ほかのテーブルのフィールド)を数式に含め、索引が生成できない状態で検索をおこなったときに大幅な速度低下・サーバマシンへの過負荷がおこる。FileMakerの検索画面で検索実行後「クエリーを処理中...」ダイアログが何分間も出ている場合は、十中八九この索引が作れないフィールドにたいしての検索がおこなわれていると思っていいだろう。

FileMaker使いなら1回はみたことがあるであろう、このダイアログ。散々待たされたあげくに「該当するレコードはありません」と表示されたときのやるせなさは計りしれない

もちろんこのスピード低下はWebアプリケーションでも発生する。ためしに索引を作る計算フィールドと索引を作らない計算フィールド、リレーションシップフィールドをふくめた計算フィールドを作成し、該当フィールドにたいして検索を実行、その結果を比較してみよう。

作成した3フィールドは次のとおり。

  • fm_calcField: すべて索引を設定する。計算式は「( f_numField_1 ) + ... ( f_numField_10 ) 」
  • fm_calcField_noIndex: 索引を保存しない。計算式はfm_calcFieldと同様
  • fm_calcField_useRField: 計算式内にリレーションシップフィールドを使用、索引は保存できない。計算式は「( fm_tune_self::f_numField_1 ) + ... ( fm_tune_self::f_numField_10 )」

作成した「fm_calcField」「fm_calcField_noIndex」「fm_calcField_useRField」

フィールド「fm_calcField_useRField」で使用するリレーション。シリアルナンバをもちいた自己リレーションだ

索引を作成するフィールドと、作成しないフィールドの索引設定

計算式にリレーション一シップフィールドがふくまれている場合、索引オプションは「計算結果を保存せず必要時に再計算する」固定となる

検索に使用するレイアウトには、誤差をすくなくするためにそれぞれの計算フィールドを配置したレイアウトを作成した。レコード数は10,000件としている。

作成した計算フィールドを一つずつ配置したレイアウトを用意した

前回同様、Apache Bench(ab)を使用して計測を実施した。requestsは10、concurrencyは1にセットしている。

全索引設定の計算フィールド「fm_calcField」 - 検索実行結果

% ab -n 10 -c 1 -A admin:admin "http://localhost/fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField&fm_calcField=%3C5&-find"

This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done


Server Software:        Apache/2.2.9
Server Hostname:        localhost
Server Port:            80

Document Path:          /fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField&fm_calcField=%3C5&-find
Document Length:        1975 bytes

Concurrency Level:      1
Time taken for tests:   0.239 seconds
Complete requests:      10
Failed requests:        0
Write errors:           0
Total transferred:      23600 bytes
HTML transferred:       19750 bytes
Requests per second:    41.77 [#/sec] (mean)
Time per request:       23.939 [ms] (mean)
Time per request:       23.939 [ms] (mean, across all concurrent requests)
Transfer rate:          96.27 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    21   24   2.5     24      28
Waiting:       21   24   2.5     24      28
Total:         21   24   2.5     25      29

Percentage of the requests served within a certain time (ms)
  50%     25
  66%     25
  75%     26
  80%     26
  90%     29
  95%     29
  98%     29
  99%     29
 100%     29 (longest request)

索引非保存の計算フィールド「fm_calcField_noIndex」 - 検索実行結果

% ab -n 10 -c 1 -A admin:admin "http://localhost/fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField_noIndex&fm_calcField_noIndex=%3C5&-find"

This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done


Server Software:        Apache/2.2.9
Server Hostname:        localhost
Server Port:            80

Document Path:          /fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField_noIndex&fm_calcField_noIndex=%3C5&-find
Document Length:        1991 bytes

Concurrency Level:      1
Time taken for tests:   30.050 seconds
Complete requests:      10
Failed requests:        0
Write errors:           0
Total transferred:      23760 bytes
HTML transferred:       19910 bytes
Requests per second:    0.33 [#/sec] (mean)
Time per request:       3005.002 [ms] (mean)
Time per request:       3005.002 [ms] (mean, across all concurrent requests)
Transfer rate:          0.77 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:  2944 3005  65.0   2992    3163
Waiting:     2944 3005  65.0   2992    3163
Total:       2945 3005  65.0   2993    3163

Percentage of the requests served within a certain time (ms)
  50%   2993
  66%   2998
  75%   3000
  80%   3069
  90%   3163
  95%   3163
  98%   3163
  99%   3163
 100%   3163 (longest request)

リレーションシップフィールドを使用した計算フィールド「fm_calcField_useRField」 - 計算実行結果

% ab -n 10 -c 1 -A admin:admin "http://localhost/fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField_useRField&fm_calcField_useRField=%3C5&-find"

This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient).....done


Server Software:        Apache/2.2.9
Server Hostname:        localhost
Server Port:            80

Document Path:          /fmi/xml/FMPXMLRESULT.xml?-db=fm_tune.fp7&-lay=fm_calcField_useRField&fm_calcField_useRField=%3C5&-find
Document Length:        1995 bytes

Concurrency Level:      1
Time taken for tests:   99.652 seconds
Complete requests:      10
Failed requests:        0
Write errors:           0
Total transferred:      23800 bytes
HTML transferred:       19950 bytes
Requests per second:    0.10 [#/sec] (mean)
Time per request:       9965.216 [ms] (mean)
Time per request:       9965.216 [ms] (mean, across all concurrent requests)
Transfer rate:          0.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:  9874 9965  91.4   9943   10169
Waiting:     9874 9965  91.4   9943   10169
Total:       9874 9965  91.4   9943   10169

Percentage of the requests served within a certain time (ms)
  50%   9943
  66%   9949
  75%   9958
  80%  10090
  90%  10169
  95%  10169
  98%  10169
  99%  10169
 100%  10169 (longest request)

全索引設定をおこなっている計算フィールドのTime per request(1リクエスト当たりの平均処理時間)はわずか0.023秒だが、索引を設定していない計算フィールドは3.005秒、さらにリレーションシップフィールドを使用した計算フィールドについては9.965秒もの処理時間がかかっていることがわかった。そのパフォーマンス差はなんと100倍から400倍。索引を気にせず計算フィールドを作ってWebアプリケーションを構築してしまうと、同時ユーザなしの検索でもこれだけ処理時間の差がでる。ユーザ数の多いWebアプリケーションではさらに時間・負荷がかかってしまうことになるのだ。

検索を実装する上でのおさらい

これらの結果から、計算フィールドを用いたFileMakerファイルにおいて注意すべき点をまとめてみよう。

  • 検索に使用するフィールドにはかならず索引を設定すること
  • リレーションシップフィールドを使用するなどの理由で索引を作成できない計算フィールドに対しては検索を実行しない
  • 計算結果が格納されたフィールドで検索をしたい場合は、「入力値の自動化>計算値を使用する」「データ格納時にスクリプトで計算結果を代入」といった方法で索引を設定できるフィールドで代用する

入力値の自動化>計算値の設定例。該当レコード変更時にしか再計算がおこなわれないのが玉に瑕だが、それ以外では充分なパフォーマンスを発揮してくれる

複雑なフラグ管理をともなう要件において、便利な計算フィールドは多用してしまいがちだ。しかし1歩間違えば、大幅な速度低下を招くことを忘れてはならない。