2009-07-07 9 views
8

私は興味深いデリムマを持っています。私はいくつかの完全なテーブルスキャンと高価な結合を行うだけでなく、いくつかの地理空間データを計算するスカラーUDFを呼び出すことを含む非常に高価なクエリを持っています。SQLServerでキャッシュテーブルを使用すると、私は狂っていますか?

最終結果は、ユーザーに提示されるデータを含む結果セットです。しかし、元の結果セットをページに分割して指定されたページだけを返すので、ユーザーに1回の呼び出しで表示したいすべてを返すことはできません。また、元のデータセット全体を取得し、グループ化および結合を適用する必要もあります関連する集計データを計算します。

要するに、UIに必要なすべてのデータをバインドするには、この高価なクエリを約5-6回呼び出す必要があります。

私は、この高価なクエリを1回計算する方法について考え始めました。その後、それぞれの呼び出しが何らかの理由でキャッシュされた結果セットを取得する可能性がありました。

私は、CacheID(Guid)をnull可能なパラメータとして取り込むストアドプロシージャにクエリを抽象化するという考えにぶつかりました。

このsprocは、この特定の結果セットを一意に識別するためにcacheIDを使用して結果セットをキャッシュテーブルに挿入します。

これは、この結果セットで動作する必要のあるsprocsが以前のクエリのcacheIDを渡すことを可能にし、データを取得する単純なSELECT文です(cacheIDに1つのWHERE句を使用)。

次に、定期的なSQLジョブを使用して、キャッシュテーブルをフラッシュします。

これはうまく動作し、ロードテストがゼロになると速度が上がります。しかし、私は、このテクニックが大量の読み込みとキャッシュテーブルに対する書き込みに伴う負荷の下で問題を引き起こす可能性があることを心配しています。

私は夢中ですか?それとも良いアイデアですか?

明らかに、私はロックの競合とインデックスの断片化について心配する必要がありますが、何か他のことについて心配する必要がありますか?

答えて

3

これまで私が行ってきましたが、特に私がアプリケーションを編集する贅沢を持っていなかったときはそうでした。私はそれが有効なアプローチだと思っていますが、一般的にアプリケーションにキャッシュ/分散キャッシュを持つことが望ましいです。これは、DBへの負荷を軽減し、スケールを改善するためです。

素朴な "ちょうどアプリケーションでやる"の解決策は、アプリケーションメッセージングバスを持たない場合にバインドに入れることができる複数のアプリケーションがDBとやりとりしていることです。 memcached)、アプリケーションごとに1つのキャッシュを持つのはコストがかかる可能性があるためです。

明らかに、理想的な解決策はページングをより安価に行うことであり、ページNを得るためにはすべてのデータを解読する必要はありません。 dbからデータをストリーミングすることは、dbのデータを同じdbにストリーミングするよりも安価であることに注意してください。これらの長いクエリの実行を担当する新しいサービスを導入して、メインアプリケーションがサービス経由でdbと対話できるようにすることができます。

+0

その後、何千もの結果をアプリに戻す必要がありますか? – FlySwat

+0

詳しくは、このデータで多くのSQL操作を実行し、結果をアプリに送信するだけです。したがって、アプリのキャッシュは非生産的なものになります。 – FlySwat

+0

@FlySwat私は、これについて仲介者を導入することは検討する価値があると考えています。長時間実行しているレポートを実行するたびにDBを適切に送信したくない場合、サービスを途中で実行するとスロットルとDBの負荷を減らす –

1

あなたのtempdbは負荷がかかっているように風船のように飛ぶことができるので、私はそれを見ます。高価なジョインをビューに配置し、ビューを索引付けする方が、すべてのユーザーの表をキャッシュする方が簡単かもしれません。

+0

結果は非常に恣意的で、多くの入力パラメータに基づいているため、ビューは膨大なものになります。これも私の最初の考えでしたが、それを実現するには何百万行ものビューが必要になることに気がつきました。 – FlySwat

+1

@FlySway、百万行は必ずしもそれほど悪くはありません。特に日の終わりにあなたがデータベースに負荷を分散し、全体的にそれを減らす方が良い場合は特にそうです。 –

関連する問題