Hint句とForceSeekについて
DBのオプティマイザが、SQLに対して正しく実行計画を組んでくれないときに、Hint句を使用してそれを強制することがあります。
例えば以下。
with (index(PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID)) がHint句です。
select
H.CustomerID,
H.OrderDate,
H.Status,
D.ProductID,
D.OrderQty
from
Sales.SalesOrderHeader H
inner join Sales.SalesOrderDetail D with (index(PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID)) on
D.SalesOrderID = H.SalesOrderID
where
H.CustomerID = 11956
and '2012-04-01' <= H.OrderDate and H.OrderDate < '2012-05-01'
本来、Hint句は最終手段であり、むやみに追加すべきではありません。
ですが、SQL Serverには、割と簡単に追加でき、かつ、効果を発揮する可能性の高いHint句が存在します。それが「 ForceSeek 」です。
で、Hint句とかよく分からないけど、目の前に遅いSQLがあって何とかしないといけない、というとき、一旦ダメもとでForceSeekを試してみよう、というのがこの記事です。
どんな時にForceSeekを追加するか
どんな時にForceSeekの指定を検討するかですが、おおむね以下のようになります。
-
DBに詳しい人と相談できない
そもそもDBに詳しい人がいるなら、Hint句の要否含めてその人と相談しましょう。
この記事自体を読む必要ないです。 -
1秒(~数秒)未満でのレスポンスを期待するSQLである
ForceSeekは、ものすごくザックリいうと「何かインデックスを使え」というDBへの指示です。バッチ処理で使うような実行時間の長いSQLでは、下手にインデックスを使うと逆に遅くなるパターンもあるのですが、OLTPの高速レスポンスを期待するようなSQLは、基本的にインデックスを使うので、ForceSeekで遅くなることがあまりありません。 -
突然遅くなったSQL
昨日までサクサク返ってきていたSQLが突然重くなる場合、原因が実行計画の変化であることが多いです。で、実行委計画の変化で遅くなるのは、大体インデックスを使わなくなった時なので、ForceSeekが効きやすいです。
ForceSeekの使い方
SQLのFrom句で、テーブル名の後ろに with (forceseek) を追加します。
基本的に、データ量が多いテーブルに対して優先的に追加します。
反対に、マスタテーブルなど、データ量が小さいテーブルに対する指定は逆効果になるパターンもあるので、様子を見ながらにしてください。
以下は指定の例です。
select
H.CustomerID,
H.SalesOrderID,
H.OrderDate,
H.ShipDate,
H.Status,
D.SalesOrderID,
D.SalesOrderDetailID,
D.ProductID,
D.OrderQty
from
Sales.SalesOrderHeader H with (forceseek)
inner join Sales.SalesOrderDetail D with (forceseek) on
D.SalesOrderID = H.SalesOrderID
where
H.CustomerID = 11956
and '2012-04-01' <= H.OrderDate and H.OrderDate < '2012-05-01'
エラーについて
ForceSeekはエラーになりにくいHint句なのですが、それでも以下のエラーが発生することがあります。
Msg 8622, Level 16, State 1, Line 1
このクエリに定義されたヒントにより、クエリ プロセッサはクエリ プランを作成できませんでした。ヒントを何も指定しないで、SET FORCEPLAN を使用しないでクエリを再実行してください。
ForceSeekは、ざっくりいうと「とにかく何かインデックスを使いなさい」という意味になるのですが、上のエラーが出たときは、DBが「ムリ。どうやったってインデクス使えない」と返してきている感じになります。
この時は、素直にForceSeekをあきらめてください。
なお、ForceSeekでこのエラーが返ってくるときは、多分、インデックス追加が必要になることが多いと思います。