2

多くの結合を含むマスター クエリを実行するアプリケーションを構築しています。このクエリ データは、アプリケーション全体で使用でき、グローバル変数で操作できます。クエリは、ページが更新されるたびに最新の結果セットを更新または取得します。そのため、リクエストの存続期間中のみ同じ状態になります。

このアプリケーションの他の部分では、このデータに対して何百もの QoQ を実行することがありますが、これは通常、再帰関数呼び出しの結果です。ただし、QoQ は優れた機能ですが、速すぎるというわけではなく、ページの読み込みが悪い日には 3000 ~ 5000 ミリ秒になることもあります。十分な速さではありません。

QoQ の実行を高速化するためにできる最適化手法や、代替方法はありますか? Duplicate() 関数に関する Ben Nadel の興味深い記事を読みました - それを使用する範囲はありますか?

あなたの考えを聞きたいです。

クレイジーな提案については心配しないでください。これは個人的なプロジェクトなので、リスクを冒してもかまいません。CF8と互換性のあるRailoでこれを実行しています。

どうもありがとう、マイケル。

4

3 に答える 3

2

QoQ のコードと複雑さを確認しないと、最善のアプローチを確実に判断するのは困難ですが、できることの 1 つは、構造体を使用して QoQ の外部のレコードにインデックスを付けることです。QoQ を使用するオーバーヘッドの多くは、新しいクエリ オブジェクトを構築することであり、構造体書き込みのみのアプローチを使用することは、たとえば元のクエリをループして比較を行うよりもはるかに効率的です。

例えば:

<!--- build up index --->
<cfset structindex = {} />
<cfset fields = "first,last,company" />
<cfloop list="#fields#" index="field">
    <cfset key = "field:#field#,value:#q[field][currentrow]#" />
    <!--- initialize each key (instead of using stuctkeyexists) --->
    <cfloop query="q">
        <cfset structindex[key] = "" />
    </cfloop>
    <cfloop query="q">
        <!--- update each key with list of matching row indexes --->
        <cfset structindex[key] = listappend(structindex[key], currentrow) />
    </cfloop>
</cfloop>

<!--- save structindex to global variable --->

<!--- output rows matching index --->
<cfset key = "field:company,value:stackexchange" />
<cfoutput>
    <cfloop list="#structindex[key]#" index="row">
        #q.last[row]#, #q.first[row]# (#q.company[row]#)<br />
    </cfloop>
</cfoutput>

これがニーズに合わない場合は、QoQ ステートメントの例と、メイン クエリに含まれるレコードの数を提供してください。

于 2011-05-05T19:46:34.130 に答える
1

まず、マスター クエリにかかった時間を調べます。ある程度の時間キャッシュでき、ページ読み込み時間のかなりの部分を占めている場合は、キャッシュします。

次に、再帰呼び出しについて見ていきます。それらを反復的にすることができれば、おそらくスピードアップするでしょう。これが常に可能であるとは限らないことを理解しています。これがあなたの最大の時間の浪費ではない場合、私は驚かれることでしょう. ただし、自分が何をしているのかを詳しく知らなければ、これを最適化するのを助けることは困難です。

また、再帰的な QoQ のストアド プロシージャのいくつかを DB サーバー上に記述することも検討するかもしれません。これは、データを迅速に処理し、効率的にスライス アンド ダイスするように設計されています。CF はそうではありません。QoQ は非常に便利ですが、スピード デーモンではありません (ご指摘のとおり)。

最後に、QoQ を使用せず、単純なフィルターを探します。むしろ、標準の cfoutput タグでマスター クエリに対してループを実行し、その場でフィルター処理するだけです。これは、マスター クエリを 1 回、結果クエリを 1 回ループするのではなく、マスター クエリを 1 回ループすることを意味します。

于 2011-05-05T16:06:08.983 に答える
1

ここには 2 つの主な解決策があります。まず、QoQ 以外のレコードを使用して CF で何かを行うことができます。私はすでにこれについて私の提案を投稿しました。もう1つは、データベースですべてを行うことです。これを行うために私が見つけた 1 つの方法は、サブクエリを一時テーブルとして使用することです。sql ステートメントをグローバル変数に保持し、現在 QoQ を使用しているのと同じ場所でそれを参照することもできますが、データベースに対して実際のクエリを実行します。DB に 1 回アクセスしてから QoQ を何度も実行するよりも遅く聞こえるかもしれませんが、効率的にインデックスが作成されていれば、実際にはそうではないでしょう。

select *
from (
    #sqlstring#
) as tmp
where company = 'stackexchange'

私は実際に、ユーザーがアクセスできるレコードと、それらのレコードで何をフィルタリングできるかの両方について、複雑な基準を持つシステムに対してこれを行いました。このアプローチを採用するということは、すべてのクエリが正しくプルされていることを確認するのではなく、内部レコードのソースを常に把握していることを意味します。

編集:実際には、可能な限り queryparams を使用する方が安全です (そして通常はより効率的です)。これは、SQLステートメントのファイルを含めることで実行できることがわかりました...

select *
from (
    <cfinclude template="master_subquery.cfm" />
) as tmp
where company = 'stackexchange'
于 2011-05-05T20:03:35.917 に答える