同じスキーマのデータベースが100個以下の環境があります。 #tempテーブルを作成してそれを削除するストアドプロシージャが各データベースにあり、非常に頻繁に実行されています(ユーザーあたり30秒程度、ユーザー数は1,000人以上)。これだけではありません。何千もの行がこの一時テーブルにロードされ、全体がダンプされます。基本的には、大量のデータが集計されます。
すべてのデータベースが同じ一時テーブルを作成するので、それらはすべて互いに競合していますか?または、各データベースはtempdbの独自のバージョンの一時テーブルを取得しますか?
Tempdbの同じページ(PAGE_LATCH
)で大量の2:3:1041580
待機が発生し、GAM、SGAM、またはPFSページではないため、競合が発生しているようです。待機の%は、すべてのデータベースにわたるこの同じストアドプロシージャからのものであるようです。これらの待機はサーバー全体の待機の90%であり、ブロッキングを引き起こしています。
私はDBCC PAGE
を実行しましたが、sysobjvalues
のようです(ヘッダーのobject_ID 60から)。私が走った:
SELECT OBJECT_Name(object_ID), *
FROM sys.dm_db_database_page_allocations(2,60,NULL,NULL,'DETAILED')
153行ありますが、ここで何を表示しているのか正確にはわかりません。 IN_ROW_DATA
のLOB_DATA
とallocation_unit_type_desc
のようです。
他のファイルとは別のボリュームに8つのtempdbファイルがあります。私は16コアを持っていますが、私の理解では、これは割り当てページではないため、ファイル数を増やすのに役立つとは限りません。 SQL Server 2017 Enterpriseの使用。
ここで一時テーブルを削除するように開発者に指示するのが最善の策のように思えますが、これにはロジックの再作成が必要になり、時間がかかります。開発者による修正を待つ間、これらのページラッチを回避するために他にできることはありますか?
この一時テーブルに数千行になる可能性のある行をロードし、全体をダンプしているだけです。基本的には、一連のデータを集約しています。
一時テーブルは、正しく使用されると、パフォーマンスと信頼性が大きく向上します。
たとえば、SQL Serverがデータの自動統計を計算できるように、またはユーザーが特定のインデックスを追加できるように、比較的小さい(狭い)中間結果セットを一時テーブルに格納すると非常に便利です。
一時テーブルは、オプティマイザが単一のモノリシッククエリよりも全体的に優れた一連のプランを作成できるようにする場合に最も役立ちます。
一時テーブルをうまく使用できない可能性もあります。 「すべてをダンプする」前に行を一時テーブルに格納するだけでは、逆効果に思えます。一時テーブルは無料ではないため、常に競合の原因となる可能性があることに注意してください。
一時テーブルを賢明な方法で使用する以外に、一時テーブルキャッシングを利用できるように配置を試みます。詳細については、私の記事 SQL Server Temporary Object Caching を参照してください。
以下のように、いくつかのパフォーマンスの最適化とバグ修正が採用されているため、最新の累積的な更新を実行していることを確認してください。
TempDBは共有リソースであるため、ある程度、はい、すべてのセッションがそのリソースをめぐって競合しています。ただし、SQL Serverは各ローカル一時テーブル名の末尾に一意の文字セットを追加するため、これはテーブル名が同じであることとは関係ありません。それは一般的に一時テーブルの作成/削除、およびそれらのテーブルに対するDML操作と関係があります(スナップショット分離を使用している場合、バージョンストアにtempdb
を使用し、トリガーはtempdb
(inserted
およびdeleted
テーブルの場合)。
「30秒に1回」というのは思っているほど頻繁ではないため、問題であるのは一時テーブル自体ではないと思います。 1秒間に数千のトランザクションがあり、多くの一時DBが使用されているシステムで作業しました。
私は見ていきます:
その一時テーブルで何が行われていますか?どのくらいのデータがロードされていますか?アップデートはたくさんありますか?行がたくさんある場合、おそらくインデックスを追加すると役立つでしょうか?
一時テーブルはトランザクション内で作成されていますか?明示的なトランザクション(つまり、BEGIN TRAN
)それともトリガー内?はいの場合、私はそのシナリオがブロッキングを引き起こすのを見ました。トランザクションの外部で一時テーブルを作成し、作成したら、トランザクション内でDMLステートメントを実行することをお勧めします。
また、SQL Server 2017 Enterpriseを使用しているので、インメモリの使用を検討することもできますOLTP=ディスクベースの一時テーブルをスワップアウトします。インメモリを作成することになると思います。ユーザー定義のテーブルタイプ。次に、そのUDTTからテーブル変数を作成します。