Dynamics CRM 2015 パフォーマンスの公開ドキュメント その 3

みなさん、こんにちは。

前回に引き続き、パフォーマンスに関する公開ドキュメントの紹介をします。
シリーズものとなっているため、まだ前回の記事を見られていない方はご覧ください。

Dynamics CRM 2015 パフォーマンスの公開ドキュメント その 1
Dynamics CRM 2015 パフォーマンスの公開ドキュメント その 2

Microsoft Dynamics CRM 2015 Performance and Scalability Documentation(英語):
https://www.microsoft.com/en-us/download/details.aspx?id=45905

Nolock ヒント

SQL Server ではクエリレベルでレコードをロックしないことをデータベースエンジンに
指定することが出来ます。Dynamics CRM のビューのクエリは、これを利用しています。
これは他の読み取り処理を待たせないことを意味しておりパフォーマンスに大きな利点が
あります。SDK を利用してクエリを行う場合、Nolock ヒントを使用することが可能です。

QueryExpression.NoLock Property:
https://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.query.queryexpression.nolock.aspx

Nolock ヒントの利用は、特に以下のケースで改善が見込まれます。

- 広い範囲のデータ
- 競合する可能性が高いリソース
- シリアル化が重要でない

一方、自動採番の仕組みのように前処理で値が変化しないことを前提としている場合、
Nolock は使用できないことに注意する必要があります。つまり、Nolock ヒントは、
競合の可能性と影響度を判断し、競合した際の値の一貫性が不要な場合に有効です。

ロックの順番

ロックの順番を意識する必要があります。例えば、User X,Y ともに更新するケースを考えてみます。
トランザクション A は User X から更新をかけます。一方、トランザクション B は User Y から
更新をかけます。その後、それぞれのトランザクションが別のユーザーを更新しようとすると
デッドロックが発生します。

image

デッドロックは、更新ロックをかける順番を考慮することで回避することが可能です。
トランザクション A,B ともに User X から更新します。
トランザクション B は、トランザクション A の User X の更新が完了するまで
待たされることになりますが、User Y の更新は User X の更新が完了していないと
実行されないことが保証されるため、デッドロックは回避されます。

image

ロック時間の最小化

自動採番などブロッキングを完全に排除できない場合、競合するレコードにアクセスする処理を
トランザクションの終わりに置くことでブロッキングの時間を最小化することが出来ます。

image

トランザクションの長さ

トランザクションが長いことは、潜在的に競合やブロッキングを発生させる
可能性を高めるため、トランザクションを短くする必要があります。

要求の最適化

実装しているクエリの最適化を行うことでトランザクションを短くできる可能性があります。

- 必要以上の情報にアクセスしていないか(カラム数、レコード数、エンティティ)
- インデックスを利用する

一連の処理におけるイベントを減らす

プラグインやワークフローを同期処理として実装している場合、トランザクションは長くなります。
非同期処理を導入することでトランザクションの長さを短くすることができます。

以下では、取引先企業を作成する際に電子メール活動を同期処理で作成した場合と、
非同期処理で作成した場合で比較しています。
それぞれの画像の 2 つ目の Create Account の開始位置を比べると一目瞭然です。 
同期処理で実装された場合、電子メール活動の作成処理が終わるまで Create Account は待たされます。
一方、非同期処理で実装された場合、電子メール活動の作成処理を呼び出した時点で、
Create Account を実行することが可能です。

image

image

更新は必要最小限にする

例えば、タスクの数をユーザー情報の項目として保持している場合、タスク作成時に毎回ユーザー情報の
更新処理を入れることになります。その場合、タスクの作成からユーザー情報の更新が 1 つの
トランザクションで実施されることとなり、トランザクションが長くなります。
こういった要件は、Dynamics CRM 2015 より搭載された集計フィールド機能を利用することで
ユーザー情報の更新処理をなくし、全体の処理を短くすることが可能です。

image

同じイベントの複数呼び出し

同じイベントに対して複数の実装している場合、潜在的にリソースが競合する可能性が高まります。
以下のように、取引先企業の作成イベントで 3 つの非同期ワークフローを設計していると、
取引先企業の更新処理にて競合が発生する可能性が高まります。
異なる開発者により実装される場合、競合を見落とす可能性があるため慎重に検討する必要があります。

image

プラグイン、ワークフロー

プラグインやワークフローのタイプにはそれぞれ意味があります。
以下の表は一般的に適切な処理とそうでないものを記載します。

ステージ

同期/非同期

プラグイン/ワークフロー

適切

不適切

Pre Validation

Sync

Workflow/ Plug-in

- 短い時間での入力値のチェック

- 長時間のアクション - 以降のステップでエラーとなった場合、ロールバックされない

Pre Operation

Sync

Workflow/ Plug-in

- 短い時間での入力値のチェック - エラーが発生した場合、プラットフォームステップの一部としてロールバックされる

- 長時間のアクション

Post Operation

Sync

Workflow/ Plug-in

- プラットフォーム内で実行できる短い処理 - 例:新しく作成したAccount の所有者のタスク作成

- 長時間のアクション - プラットフォームのステップ完了後にエラーを起こすべきでない

Not in event pipeline

Async

Workflow/ Plug-in

- (ユーザー操作に影響が見込まれる)中時間のアクション - エラーが発生してもロールバックされない

- 非常に長時間のアクション - 非常にコストが小さい処理。非同期を生成するのに必要なオーバーヘッドを考慮すると非効率のため

N/A

 

Custom Actions

- Web リソースなど外部から実行されるアクション

- 常にプラットフォームイベントから呼び出される処理(プラグイン、ワークフローを利用すべき)

 

また、プラグインやワークフロー内に長時間を要するバッチ処理を実行することは想定されていません。
別のサービスとして実行してください。

セキュリティ設定

セキュリティ設定の拡張は、コストのかかる操作のため慎重に実施する必要があります。

- チームの設定
   チームにユーザーを追加する場合、デッドロックを避けるため常に同じ順序でユーザーを追加します。
   ユーザーを更新する場合、必要以上のキャッシュを避けるため必要なユーザーのみ更新します。
- レコードの所有者となっているチームの変更
   チームのユーザーを定期的に変更する場合、毎回 Web サーバー上のキャッシュを更新するため、
   特に所有者となっているチームの更新には注意が必要です。
- 大量のチームや部署の追加
   大量のチームや部署の追加は、多くの複雑な計算が必要となるため慎重に実施する必要があります。 
- 共有
   所有者をアサインする場合、共有範囲を考慮する必要があります。
- ユーザー情報の更新
   例えば、ユーザー情報にオープンの活動数を保持するような設計は極力控えてください。
   ユーザー情報が更新されるたびに、コストの高い再計算処理が実行されます。

ダイアグラムの作成

ブロッキングや問題を事前に防ぐツールとして、処理をダイアグラムに図式化する方法があります。
例えば、既存の取引先企業の作成処理にタスクを作成するイベントを追加しようと検討している場合、
図式化することで処理がループすることを事前に検知することができます。

image

分離レベル

SQL Server をより楽観的な分離レベルに変更することで、多くのブロッキングの問題に対処できます。
例えば、既定である Read Commited から Read Committed Snapshot Isolation (RCSI) に変更した場合、
読み取り時のブロッキングから解放されます。一方、この変更により TempDB にある時点の情報が
格納されるため、データベース使用量の増加、TempDB への書き込み処理が追加されます。

分離レベルの変更は一つの有効な手段ですが、
設計の最適化によるブロッキングの回避のほうがはるかに有益なアプローチです。

最後に

- ロックやトランザクションは、システムに必要な仕組みであるが誤った使い方をすると問題を招く
- プラットフォームの制約はシステムを保護するために必要なのもの
- トランザクションの仕組みを念頭に置いた設計実装は、パフォーマンスの改善に最も有益な手段

 

まとめ

パフォーマンスに関して 3 回に渡り紹介してきましたがいかがだったでしょうか。
パフォーマンスはユーザー操作に直結する重要な項目です。トランザクションやロックの
仕組みを理解し、適切に利用いただくことでよりパフォーマンス改善につながります。
ドキュメントには、紹介しきれなかったブロッキングの診断方法など有効な情報が
含まれています。是非合わせてご確認ください。

- プレミアフィールドエンジニアリング 河野 高也