SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

SQL Server で並列クエリになるように明示的に調整する方法

leave a comment

以前、次の投稿で並列クエリになるようにする調整方法を投稿しました。

最近、これらの情報を確認する機会がありましたので、改めて情報を整理しておきたいと思います。

並列クエリとは?

SQL Server の並列クエリについては クエリ処理アーキテクチャ ガイド並列クエリ処理 に記載されています。この情報の他には次の情報も参考となります。

SQL Server のいくつかの操作では複数のワーカースレッドを使用してクエリ内の処理を実行することができます。

並列処理として実行された処理については、次の画像のように実行プラン内のアイコンが並列処理のマークがついたものとなります。

image

並列処理として実行された処理は、次の画像のように一つの処理が複数のスレッドで実行されます。

image

これにより CPU の使用時間は増加しますが、複数のスレッドによりデータの処理が行われるため処理時間の短縮につながる可能性があります。

高速なストレージを使用していても、1 スレッドで処理可能なスループットは上限がありますので、単一のクエリでストレージ性能を最大限活用するためには並列クエリによる複数スレッドの処理が必要となるケースがあります。

SQL Server が並列クエリを使用するかどうかについては、実行プランのコストをベースに制御が行われており、サーバー構成: 並列処理のコストしきい値 の設定 (cost threshold for parallelism) の設定を使用して並列プランとして実行するかどうかが決定されます。

cost threshold for parallelism はデフォルトでは 5 に設定されており、一般的には変更することはないため、初期設定のコストで SQL Server のオプティマイザに任せて並列クエリの使用可否が判断されるケースが大半ではないでしょうか。

 

手動で並列クエリになるように調整する方法

基本的には SQL Server のオプティマイザに任せて並列クエリの利用有無が変わってきます。

低コストなクエリでは並列クエリにならない可能性が高いのですが、ワークロードによっては低コストのクエリでも並列クエリ化をしたいケースがあります。

前述の「cost threshold for parallelism」の設定を小さくすることで、低コストなクエリでも並列クエリとして実行できるケースがありますが、この設定はインスタンス全体に影響を与えるものとなり影響範囲が大きくなるため、クエリ単位で制御をしたいことがあります。

そのようなケースでは次のような方法を使用することで、クエリ単位で並列クエリになるような調整ができる可能性があります。

  1. 「DBCC SETCPUWEIGHT」を使用することで、意図的に CPU コストを増加させる
  2. OPTION 句 で「QUERYTRACEON 8649」を使用する
  3. OPTION 句 で「USE HINT(‘ENABLE_PARALLEL_PLAN_PREFERENCE’)」を使用する

これらの方法を使用することで、クエリ単位で並列クエリとして実行される可能性が出てきます。

以下のクエリを例として、各方法を使用してみます。

DBCC FREEPROCCACHE
GO

SELECT COUNT(*) FROM LINEITEM WHERE L_ORDERKEY BETWEEN 10 AND 1000
GROUP BY L_COMMENT
GO

 

このクエリはコストが低いクエリとなるため、通常の実行方法では各処理がシングルスレッドで実行されます。

image

このクエリを各方法で並列クエリ化を行ってみたいと思います。

 

DBCC SETCPUWEIGHT

DBCC FREEPROCCACHE
GO

DBCC SETCPUWEIGHT(1000)
GO

SELECT COUNT(*) FROM LINEITEM WHERE L_ORDERKEY BETWEEN 10 AND 1000
GROUP BY L_COMMENT
GO

 

QUERYTRACEON 8649

DBCC FREEPROCCACHE
GO

SELECT COUNT(*) FROM LINEITEM WHERE L_ORDERKEY BETWEEN 10 AND 1000
GROUP BY L_COMMENT
OPTION(QUERYTRACEON 8694)
GO

 

ENABLE_PARALLEL_PLAN_PREFERENCE

DBCC FREEPROCCACHE
GO

SELECT COUNT(*) FROM LINEITEM WHERE L_ORDERKEY BETWEEN 10 AND 1000
GROUP BY L_COMMENT
OPTION (USE HINT('ENABLE_PARALLEL_PLAN_PREFERENCE'))
GO

 

これらの方法を使用することで、並列クエリのコストのしきい値を超えないクエリについても、以下のように並列クエリ化することができる可能性があります。

image

 

手動で並列化をする場合の注意点

アンドキュメントな手法ということを意識する

手動で並列化をする場合の注意でですが上述の 3 種類のいずれの方法も「アンドキュメント (Undocumented) 」な方法となり、Microsoft からサポートを受けることはできない方法となるということです。

「ENABLE_PARALLEL_PLAN_PREFERENCE 」については、ヒント句として使用していますが、クエリ ヒント (Transact-SQL) でも公開はされておらず、sys.dm_exec_valid_use_hints (Transact-SQL) でも公開されていないヒントとなります。

そのため、これらの方法は正規の並列クエリを実行するための方法ではないため、使用することで何らかの問題が発生した場合、サポートに連絡をしても、手動で並列化を行う方法を継続して使用することはできず「使用することをやめる」という対応しかできない可能性が高いです。

また、正規のコストで並列化を実施しているわけではありませんので、並列化を行っても次の画像のように各スレッドで均等に処理が行われず、処理のオーバーヘッドのみが増加する可能性があることも意識しておく必要があります。

image

 

必要となる権限

「DBCC SETCPUWEIGHT」「QUERYTRACEON 8649」(DBCC TRAEON) については、DBCC コマンドの実行が必要となるため、「sysadmin」の権限が必要となります。

「USE HINT(‘ENABLE_PARALLEL_PLAN_PREFERENCE’)」については、ヒント句として実行されるため、data_reader のようなデータ参照ができる少ない権限のユーザーでも使用することができます。

高い権限を持たせずに、並列クエリ化の実行を検討したいのであれば、「USE HINT(‘ENABLE_PARALLEL_PLAN_PREFERENCE’)」が候補として挙がるのではないでしょうか。

Share

Written by Masayuki.Ozawa

2月 25th, 2025 at 10:48 pm

Posted in SQL Server

Tagged with

Leave a Reply