みんなに優しく、解りやすくをモットーに開設しています。 以下のルールを守りみんなで助け合いましょう。
1.ファイルメーカーで解らない事があればここで質問して下さい。 何方でも、ご質問・ご回答お願いします。 (優しく回答しましょう)
You are not logged in.
以前から何度かお世話になっております。
宿泊予約管理システムを作成しておりまして、
カレンダー関係の構築では、hiro様のToDoカレンダーや宿帳v4等にて勉強させていただきました。
現在、ローカル環境にて開発を進めており、予約カレンダーのところでは、例によって繰り返し回数42回の繰り返しフィールドを使いながら、
その繰り返し計算式にexecuteSQL関数を用いて、その日ごとの予約件数だとか、予約者の情報等を柔軟に取得し、レイアウト上で表示させるようにしています。
これが、ローカルではさっくさくと動いていたのですが、FMCloudでホストして動かした途端、executeSQLを使う場面でのパフォーマンスの低下が著しく、どうしたものかと思案中です。
パフォーマンスに影響を与える要因は、それこそ本当に多種多様だと思いますので一概には言えないと思うのですが…。
内容を表示する42回の繰り返しフィールド(計算式・非保存)を、テキストフィールドにしておいて、サーバー上でexecuteSQLを実行するスクリプトを適宜走らせ、スクリプトから値を格納していく方が、パフォーマンスは良いと思われますか? 経験豊富な皆さんのお知恵をお借りしたいです。
基本的な構成としては、
・カレンダー日付[42]
・祝日[42]
・予約室数[42]
・料金ランク[42]
というかたちで、非保存の計算式で42回の繰り返しフィールドとして定義されているフィールドが4つあるテーブルでのレイアウトです。
こちらで試してみたのは、この4つの繰り返しフィールドのうちの、予約室数[42]と料金ランク[42]をレイアウトから削除したところ、体感的に2倍はパフォーマンスが改善されました…。
レイアウトで欲張りすぎない、ということもあるのでしょうね。
オブジェクトスタイルに関しては、ちゃんとテーマに保存してあるスタイルのみを使っています。
また、FMCloudのインスタンスについては、t2.mediumからm4.largeまで試しましたが、この部分でのパフォーマンス改善にはほとんど変化がなく、むしろAdmin Consoleから使用状況をみるかぎり、
network throughputの部分でも、数十bytes per second程度しか動いていませんので、無駄に性能を余らせているだけになって、結局t2.mediumに戻しました。
Cloudにしてここまで極端に遅くなってしまうなら、簡易共有機能である「FileMaker ネットワーク共有」で共有したほうが、費用もかからずパフォーマンスも高いからいいのかな、とも考えています。
用途的には社内の基幹業務アプリケーションですが、同時接続5台という制限がそこまでネックになるわけではない人数で使いますので…。
もちろん、セキュリティーが脆弱という問題はあるかと思いますが。
悩みます。
Offline
FMCloud環境も経験もないので、ただの机上の推論ですが、
思いつくままに、
FMCloudはAWS(アマゾンが提供する共有サーバ)上のサービスだから、自家サーバとローカル
ネットワーク LANで構築するFMネットワーク共有の方がパフォーマンス的には上でしょう。
ExecuteSQLは絶対的に遅く、高負荷です。FMにとっての外国語SQLで
わざわざ仕事をさせられるのですから!
パフォーマンスの問題を抱えるなら、SQLは止めて、FM機能1本で行きましょう。
内容により一概には言えませんが、計算式やれることなら、スクリプトより
計算式の方が早いことが多いように思います。
繰り返し計算フィールドは概して重いと感じます。繰り返し数による比例幅より大きく感じます。
試しに、繰り返し[1000回]計算フィールドとかで軽くテストして体感してみて下さい。
パフォーマンスの問題を抱えるなら、4つの繰り返し[42]フィールドを、その4項を
4行一覧リストにまとめて、1つの繰り返し[42]フィールドだけに出来ませんか?
などなど・・・・・
Offline
繰り返しフィールドの計算の重さではないかと思います。
できる限り、計算そのものはベースのテーブルで行ってしまい。繰り返しフィールドは表示のみ、に徹するのがいいのでは。
Offline
Hiro様、Shin様、ありがとうございます。
お二方からご指摘いただきました繰り返しフィールドの運用について、ちょっと考え直したいと思います。
スケジュールの都合から、今回はひとまず、FM単体のネットワーク共有機能で最大5台接続の運用を始め、時期を見て、再度FMCかFMServerか、それに向けでパフォーマンスの改善を図っていくことにします。
Offline
同じ環境(FMCloud on AWS t2.midium)で受発注システムを運用しています。
FMCloudで運用しようが、どこかのレンタルサーバーにWindowsサーバーを入れて運用しようが結果は変わりません。ローカル環境のLAN回線とはそもそも比較になりません。
>>サーバー上でexecuteSQLを実行するスクリプトを適宜走らせ、スクリプトから値を格納していく方が、パフォーマンスは良いと思われますか?
リレーションの複雑さと走査するデータ量によりますが、雲泥の差です。
自分もExecuteSQLで値を取得してそれを繰り返しフィールドで表示させるってのはよく使いますが、ほぼサーバー上でSQLを走らせます。結果をローカルの変数なりグローバルフィールドなりに一旦格納してから、それを繰り返しフィールドで参照させます。スクリプトの結果の受け渡しが必要ですが、こんな感じで組みます。
"script_server"はこの一行だけ 現在のスクリプト終了[テキスト結果 ここにExecuteSQLを直接記述]
発火点の"script_local"は サーバー上のスクリプト実行[script_serverを指定]
変数を設定 $data 値 Get(スクリプトの結果) もしくはフィールド設定 "some gloval_fiels" ; Get(スクリプトの結果)
上記二つを発展させれば汎用的に運用できるかと思います。
受け取る(local)側のデータ処理はフィールド定義の計算式で。
一度大量のデータを走査するSQLを組んで比較したらわかります。4G回線のiPhoneからでも全く遅さを感じません。
集計や繰り返しフィールドへのデータ投入は基本サーバー上でデータを抽出してからでないと遅くて使い物になりませんし、現状のネットワーク速度ではそうせざるを得ないでしょう。
しかしサーバーで処理させれば、程度にもよりますが、グラフ描画用の集計データもボタンを押すごとにサーバーから逐一SQLで取得して、動的にサクサク描画を変化させたりできます。それくらい実用的です。
現状のインターネット回線速度と社内LANの速度とでは安定度も含めて相当開きがありますので、重い処理は全部サーバーに投げるという考えで処理を組む必要があると思います。
注意点はJOINが何個もある複雑なリレーションのSQLはサーバーでも遅いです。もしかしたらそれもSQLの投げ方で解決できるのかもしれませんが、自分はまだそこまで精通してないので。
Offline
>#5 calafateさん 『重い処理は全部サーバーに投げるという考えで処理を組む必要がある』
なるほど、それを実装する手段に、ExecuteSQLがむしろ極めて有効ということですネ。
つまり、丁度バーチャルリスト的な考え方をサーバ・クライアント間に適用するわけで……。
サーバでバーチャルリスト(改行配列の軽量化データ)を生成し、それをクライアントで受信、目的に合わせ展開・利用。
そこで、1つ提案、
> 『発火点の"script_local"は サーバー上のスクリプト実行[script_serverを指定]』
で、クライアントの自由なSQL命令文をスクリプト引数で送信し、サーバでEvaluate("スクリプト引数")で命令実行するようにすれば、
ほぼ完全な汎用スクリプト・システムとなりませんか?
Offline
>calafate様
ありがとうございます。
「現在のスクリプト終了」のテキスト結果にSQLを記述し、親スクリプトで結果を受け取るという方法もあるのですね、びっくりしました。
これならコードを節約できるうえに、わかりやすいですね。とても勉強になります。
>ローカル環境のLAN回線とはそもそも比較になりません。
>リレーションの複雑さと走査するデータ量によりますが、雲泥の差です。
はっきりと言っていただけて、救われたような気持ちです。
FMCの進化をウォッチしつつ、当面はLANのFMServerで運用をしていくことにしました。
>Hiro様
なるほど、素晴らしいアイデアですね…。
ユーザーの画面上からSQLが実行できるようになると、当初の設計にないデータセットの集計処理をしたくなったとき、すごく便利です。
Offline
Hiroさん
繰り返しフィールドは自動ナンバリングされてますから、Virtual Listと組み合わせしやすいですし、最適なコンビです。
自分はVirtual ListでのSQL取得はほぼサーバーに投げます。
SQLでテキストブロックで取得さえすれば、その時点で計算の連鎖が切れてますから、クライアント側でどんなに複雑な計算しようと速度的に問題になることはあまりないです。
Shinさんのおっしゃる通り
>計算そのものはベースのテーブルで行ってしまい。繰り返しフィールドは表示のみ、に徹する
ですね。
Webアプリでは、クライアントのブラウザーが表現用でサーバーが処理用として分離しているように、今のFileMakerもそういった処理をしやすいようになってきていますね。JSON関数とかcURLとか。FileMaker社も引数はJSONに収めるのを推奨しているようですし。
>クライアントの自由なSQL命令文をスクリプト引数で送信し、サーバでEvaluate("スクリプト引数")
なるほどEvaluateを使うと引数としてまんまExecuteSQLを投入できますね。Evaluate関数はどうも感覚的に使いこなせず、思いつきませんでした。"SQL"文とWHERE以下のパラメーターをそれぞれJSONに入れて渡すのはたまにやりますが、Evaluateなら一発ですね。今度やってみます。
nimさん
FileMakerCloudに触れると自然とAWSの世界に触れるようになるので、それはそれで面白いですよ。まさにコンピューティング最前線って感じです。自分はほんの少ししか齧れませんが。
Offline
横から失礼します。
下記のスクリプトについて非常に興味があり、試してみたのですが、どうもExecuteSQL文の引き渡しがうまくいきません。
どなたか具体的なスクリプトの例を教えていただけないでしょうか?
>そこで、1つ提案、
>> 『発火点の"script_local"は サーバー上のスクリプト実行[script_serverを指定]』
>で、クライアントの自由なSQL命令文をスクリプト引数で送信し、サーバでEvaluate("スクリプト引数")で命令実行するようにすれば、
>ほぼ完全な汎用スクリプト・システムとなりませんか?
発案者ですが、Cloud環境無いので、素人の夢想ということで…………。
元々の発想としては、
『AWSのWebサービスで FileMaker API 風な利用法ができるのでは?』
と言う事でした。
通常 Web API は、Text/JavaScript ですが、これを Text/ExecuteSQL へ替えるというアイデアです。
そこで、ExecuteSQL構文をテキストに換える必要が生じますが、その際、
テキスト式内3重入れ子の「"」文字が記述ミスを起こし易くもっとも注意です。
そこで、3重は避けてせめて2重にするためによくやるのは、ExecuteSQL構文を
テキストフィールドに格納(グローバル格納)して、スクリプト引数へはその
フィールド値を利用します。
また、そのグローバルフィールドを繰り返しフィールドにしておけば、
必要なExecuteSQLコードが種々あっても一か所で保管・選出ができます。
Offline
nozawagakさんへ
まず、ExecuteSQL式が正しいという前提で
スクリプト1
現在のスクリプト終了 テキスト結果[ Get(スクリプト引数) ]
スクリプト2
サーバー上のスクリプト実行[ スクリプト1を指定 ; 引数 (ここにExecuteSQL式を記述); 終了するまで待つ ON ]
カスタムダイアログを表示 [Get(スクリプトの結果)]
これでスクリプト2をテストしてみて下さい。Evaluate使わなくても動作しました。カスタムダイアログに正解が表示されます。
私のEvaluate関数の理解不足かもしれませんが、今の所FM17ではExecuteSQL式をそのまま引数で渡して問題ありません。
これならHiroさんのおっしゃるように
>>グローバルフィールドを繰り返しフィールドにしておけば、
必要なExecuteSQLコードが種々あっても一か所で保管・選出ができます。
で汎用的に使えそうです。
ちなみにCloudでも社内LAN運用でもサーバー---クライアント運用であればスクリプトは全く同じです。
Offline
>#11 calafateさん『サーバー上のスクリプト実行[ スクリプト1を指定 ; 引数 (ここにExecuteSQL式を記述); ]』
この(ここにExecuteSQL式を記述)だと、式ではなくSQL計算結果値が引数に引き渡されることとなり、
その結果、当然の帰結として、
>#11『今の所FM17ではExecuteSQL式をそのまま引数で渡して問題ありません。』
となり、Evaluateで引数式を実行させる意味がありません。
つまり、『サーバサイドスクリプトでSQL命令文を実行させ、クライアントの負荷分散を図る』
という本来意図したものになりません。
やはり、こうでないとダメでは?
・スクリプト1 現在のスクリプト終了 テキスト結果[ Evaluate(Get(スクリプト引数)) ]
・スクリプト2 サーバー上のスクリプト実行[ スクリプト1を指定 ; 引数:"ExecuteSQL(\"SQL構文\")" ]
また、"ExecuteSQL(\"SQL構文\")" は、SQL構文内にもさらに「"」記述箇所があり、都合3重のエスケープ処理は非常に面倒なので、
テキストフィールドに保存することで、一番外側の「"」を取り去ることができ、通常記述と同じ2重入れ子にする、回避策です。
Offline
Hiroさん
そうなんですね!引数にそのまま入れるとサーバーに渡す前に計算されてしまうと。今回小さなデータでテストしたので気づきませんでした。
それでEvaluateを使うのですね。
大変勉強になります。
>>"ExecuteSQL(\"SQL構文\")" は、SQL構文内にもさらに「"」記述箇所があり、都合3重のエスケープ処理は非常に面倒なので、
テキストフィールドに保存することで、一番外側の「"」を取り去ることができ、通常記述と同じ2重入れ子にする、回避策です。
このエスケープ処理が本当に目が回ります。なのでどうしても避けてしまいます。
SQL式をテスストフィールドに保管しておくとエスケープ処理が少なくなるという事ですね?
Offline
calafate様、Hiro様
ご説明ありがとうございます。
ご説明いただきましたおかげで動作するようになり、サーバー側での処理の速さに驚きました。
検証を行う中でグローバルフィールドのSQL文の書き換えがスクリプト内で可能であれば更に汎用的に使えると思い
いろいろ試したのですがSQLの結果が書き込まれるなどSQL文自体の書き換えができませんでした。
なにかいい方法はないでしょうか?
>#14 『検証を行う中でグローバルフィールドのSQL文の書き換えがスクリプト内で可能であれば更に汎用的に使える』
実装は簡単です。
SQL文内の書き換えする箇所に<<マーカ>>を書いておいて、Substitute(グローバルフィールド; ["<<マーカ>>";"書換文"])
をスクリプト引数に設定するだけです。
また、サーバ側の特定のフィールド値などを利用する場合なら、SQLのダイナミックパラメータ・標準機能を利用すれば良いですし、
Offline
>>Hiroさん
Substituteで値を出し入れできて便利ですね。大変勉強になります。
まとめるとこんな感じでしょうか
1.テキストフィールドに普通にExecuteSQL式を書いて入れておく
2.ローカルの発火側はサーバー上のスクリプト実行で引数に1で指定したフィールドを指定
3.サーバー側のスクリプトは 「現在のスクリプト終了 結果[Evaluate(Getスクリプト引数)]」
4.SQL式でWHERE項目など随時変更する場合はその箇所を "Mark"とでもしておいて、引数に渡す時に
サーバー上のスクリプト実行 引数(Substitute(1で指定したフィールド;"Mark"; "値を使いたいフィールド名とか") )
例)
テキストフィールド(フィールド1)に入れる式
ExecuteSQL
(
"
SELECT *
FROM \"テーブル名\"
WHERE \"日付\" = ?
"
;""
;""
;"Mark"
)
引数として
サーバー上のスクリプト実行 [ Substitute(フィールド1; "Mark" ; "取得したい日付を持つフィールド名" ) ]
みたいな感じですかね。かなり汎用的に使えそうです。ありがとうございます。
Offline
SQL文は固定させておいて、DB側にEvaluate() を使った計算フィールドを用意するか、全置換させておき、それを評価する、という方法でも、同様のパフォーマンスを得られる可能性はありますね。
SQL は使っていませんが、運用中のもので、結構面倒な処理で時間がかかる部分をそれで処理しています。時間は数分の1程度になります。
Offline
ご説明ありがとうございます。
このスレッドのおかげで今まで時間のかかっていた処理が短時間で処理できるようになりました。
ありがとうございました。
[ Generated in 0.008 seconds, 11 queries executed - Memory usage: 589.3 KiB (Peak: 625.84 KiB) ]