0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQL Server】このHint句だけは覚えておくべき【ForceSeek】

Posted at

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でこのエラーが返ってくるときは、多分、インデックス追加が必要になることが多いと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?