4


2

クエリ実行プランを保存して、後で使用できるようにする方法

私のアプリケーションは、SQLサーバーデータベースに対してクエリを実行します。

多くの場合、実行計画の利点を見ることができます。たとえば、ボタンをクリックして初めて

SELECT * from Tasks
WHERE IdUser = 24 AND
  DATE < '12/12/2010' and DATE > '01/01/2010'

最初は15秒かかり、次の場合は8秒かかります。

編集:パラメータ化されたクエリを使用します。

したがって、2回目には7秒の改善があります。

これで、アプリケーションを再度実行すると(新しいデータベース接続を行うため)、最初は15秒かかり、2回目は7 …​

SQL Serverに実行計画を保存するように指示するにはどうすればよいですか? または、すでに計算された実行計画のメリットをどのように得ることができますか? 異なるユーザーが同じクエリを実行すると、その場合はおそらくIdUserが異なる場合でも、SQLサーバーに同じ実行計画を使用するのに十分スマートであると伝える方法です。

ソフトウェアにはいくつかのパラメーターがあるので、クエリの次の実行でMinDateとMaxDateが異なる場合がありますが、これはクエリプランに影響しますか?

3 回答


2


パラメータ化されたクエリを使用して、プランがキャッシュされる可能性を最大化する

SELECT * from MYTasks
WHERE IdUser = @UserId AND DATE < @enddate and DATE > @startdate

SQL Serverは自動パラメータ化を行いますが、これについてはかなり保守的です。

以下から、プランの再利用に関する洞察を得ることができます。

SELECT usecounts, cacheobjtype, objtype, text, query_plan, value as set_options
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_query_plan(plan_handle)
cross APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
where text like '%MYTasks%' and attribute='set_options'


2


SQL Serverがこれを行います-実行プランは、使用可能なスペースがある限り保存されます。

ただし、実行プランを保存して再利用する可能性を高めるために多くのことを行うことができます-注意する必要があるのは*同一の* SQLクエリを作成することです-余分なスペースに至るまで、SQL Serverは2つのクエリを異なり、既存のクエリプランを再利用しません。

したがって:

  • クエリの一貫性を保つ-常に同一のものを綴る マナー(大文字/小文字、大文字、「dbo。」プレフィックスなどに注意してください)

  • リテラル値の代わりにパラメーターを使用します。リテラル値を使用する場合 クエリプランは再利用されず、プランキャッシュが不必要にいっぱいになります。

  • `SELECT *`を避けるようにしてください-これは、クエリオプティマイザーが少ないことを意味します オプション-すべての列が必要なため、通常はクラスター化インデックスでスキャンを実行する必要があります。 本当に必要な3、5、6列を指定すると、クエリを対象とするインデックス(関心のあるすべての列を含む)が存在する可能性があるため、クエリ分析はそのインデックスを使用して、インデックススキャン/インデックスシーク(およびそのプランの再利用)。

したがって、SQLの代わりに、これを代わりに使用してください。

SELECT (list of fields)
FROM dbo.MYTasks
WHERE DATE < @EndDate and DATE > @StartDate

これにより、クエリプランの再利用が大幅に増加します。


0


SQL Server Profilerを実行しましたか? もしそうなら、ステートメントのコンパイルと実行計画の生成に余分な時間がかかりますか?

問題の説明から、追加の7秒がデータベースへの初期接続をセットアップする時間になる可能性があります。 たぶん、あなたはすでにこれを除外しているでしょう。 知りません。

追加の懸念事項は、データキャッシュです。 データに初めてアクセスすると、SQL Serverはそのデータをキャッシュに読み込みます。 これにより、後続のクエリの時間を短縮できます(すべてのデータを保持できると仮定)。