sql >> データベース >  >> RDS >> Database

#tempテーブル作成追跡のオーバーヘッド

    前回の投稿(「その#tempテーブルの所有者は誰ですか?」)で、SQL Server 2012以降では、拡張イベントを使用して#tempテーブルの作成を監視できることを提案しました。これにより、tempdbで多くのスペースを占める特定のオブジェクトを、それらを作成したセッションと関連付けることができます(たとえば、スペースを解放するためにセッションを強制終了できるかどうかを判断するため)。私が話し合わなかったのは、この追跡のオーバーヘッドです。拡張イベントはトレースよりも軽いと予想されますが、完全に無料の監視はありません。

    ほとんどの人はデフォルトのトレースを有効のままにしておくので、そのままにしておきます。 SELECT INTOを使用して両方のヒープをテストします (デフォルトのトレースは収集しません)およびクラスター化インデックス(収集します)。バッチをベースラインとして独自に計測し、拡張イベントセッションを実行してバッチを再実行します。また、SQLServer2012とSQLServer2014の両方に対してテストします。バッチ自体は非常に単純です。

     SET NOCOUNT ON; SELECT SYSDATETIME(); GO-この部分はヒープバッチに対してのみ実行します:SELECTTOP(100)[object_id] INTO #foo FROM sys.all_objects ORDER BY [object_id]; DROP TABLE #foo; --この部分はCIXバッチに対してのみ実行します:CREATETABLE #bar(id INT PRIMARY KEY); INSERT #bar(id)SELECT TOP(100)[object_id] FROM sys.all_objects ORDER BY [object_id]; DROP TABLE #bar; GO 100000 SELECT SYSDATETIME(); 

    どちらのインスタンスでも、4つのCPU、16 GBのメモリ、SSDのみを備えたVMで、4つのデータファイルとTF1117およびTF1118が有効になっているtempdbが構成されています。バッチ自体への観察された影響を増幅するために、意図的に小さな#tempテーブルを作成しました(#tempテーブルの作成に時間がかかったり、過度の自動成長イベントが発生したりすると、溺れてしまいます)。

    これらのバッチを各シナリオで実行しました。結果は、秒単位のバッチ期間で測定されました。


    100,000個の#tempテーブルを作成するバッチ期間(秒単位)

    データの表現を少し変えて、100,000を期間で割ると、各シナリオで1秒あたりに作成できる#tempテーブルの数を表示できます(読み取り:スループット)。これらの結果は次のとおりです。


    #tempテーブルは各シナリオで1秒あたりに作成されます

    結果は私には少し驚きました。SQLServer2014の熱心な書き込みロジックの改善により、少なくともヒープの数が大幅に高速化されると予想していました。 2014年のヒープは、ベースライン構成で2012年よりもわずか2秒速かったが、拡張イベントによって時間がかなり長くなった(ベースラインよりも約10%増加)。一方、クラスター化されたインデックス時間はベースラインで2012年に匹敵しましたが、拡張イベントを有効にすると18%近く増加しました。 2012年には、ヒープとクラスター化インデックスのデルタははるかに控えめで、それぞれ1.1%と1.5%でした。 (明確にするために、どのテストでも自動成長イベントは発生しませんでした。)

    それで、私がよりスリムで意味のある拡張イベントセッションを作成したらどうなるだろうと思いました。確かに、これらのアクション列の一部を削除することはできます。おそらく、ログイン名とspidだけが必要であり、アプリ名、ホスト名、および潜在的に高価なsql_textを無視できます。おそらく、コミットに対して追加のフィルターを削除し(2倍のイベントを収集しますが、フィルタリングに費やすCPUは少なくなります)、複数のイベントの損失を許可して、ワークロードへの潜在的な影響を減らすことができます。この無駄のないセッションは次のようになります:

     CREATE EVENT SESSION [TempTableCreation2014_LeanerMeaner] ON SERVER ADD EVENT sqlserver.object_created(ACTION(sqlserver.server_principal_name、sqlserver.session_id)WHERE(sqlserver.like_i_sql_unicode_string([object_name]、N'#%') (SET FILENAME ='c:\ temp \ TempTableCreation2014_LeanerMeaner.xel'、MAX_FILE_SIZE =32768、MAX_ROLLOVER_FILES =10)WITH(EVENT_RETENTION_MODE =ALLOW_MULTIPLE_EVENT_LOSS); GOALTER EVENT SESSION [TempTableCreation2014_LeanerMeaner] 

    ああ、いや、同じ結果。ヒープの場合は3分強、クラスター化インデックスの場合は7分弱です。余分な時間が費やされていた場所をより深く掘り下げるために、SQL Sentryを使用して2014インスタンスを監視し、拡張イベントセッションを構成せずにクラスター化インデックスバッチのみを実行しました。次に、バッチを再度実行しました。今回は、より軽いXEセッションを構成しました。バッチ時間は5:47(347秒)と6:55(415秒)でした。これは前のバッチと非常に一致しています(監視が期間にこれ以上貢献しなかったことを嬉しく思います:-)) 。ドロップされたイベントがないこと、および自動拡張イベントが発生していないことを検証しました。

    SQL Sentryダッシュボードを履歴モードで確認しました。これにより、両方のバッチのパフォーマンスメトリックを並べてすばやく表示できました。


    SQL Sentryダッシュボード、履歴モード、両方のバッチを表示

    両方のバッチは、ネットワーク、CPU、トランザクション、コンパイル、キールックアップなどの点で実質的に同一でした。待機には若干の違いがあります。最初のバッチでのスパイクは排他的にWRITELOGでしたが、CXPACKETのマイナーな待機がいくつか見つかりました。 2番目のバッチ。真夜中過ぎの私の作業理論は、観察された遅延のかなりの部分は、拡張イベントプロセスによって引き起こされたコンテキストスイッチによるものである可能性があるというものです。 XEが内部で何をしているのかを正確に把握しておらず、2012年から2014年の間にXEでどのような基本的なメカニズムが変更されたのかわからないため、これから私がxperfやWinDbgの方が快適です。

    結論

    いずれにせよ、#tempテーブルの作成の追跡は無料ではないことは明らかです。コストは、作成する#tempテーブルの種類、XEセッションで収集する情報の量、さらにはバージョンによって異なる場合があります。使用しているSQLServerのしたがって、ここで行ったのと同様のテストを実行して、この情報を収集することが環境でどれほど価値があるかを判断できます。


    1. Azure SQLデータベース管理のヒントとヒントの試験(DP-300)

    2. Oracleウォレットを使用する場合の正しいJDBCURL構文は何ですか?

    3. MySQLで行をフィルタリングする句

    4. MySQLの各カテゴリのトップ10レコードを選択