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

SQLServerデータベースTempDBの予期しない増大を検出して防止する方法

    各SQLServerインスタンスには、TempDBと呼ばれるシステムSQLServerデータベースが含まれています。これはすべてのデータベース接続で一般的であり、ほとんどすべてのクエリでTempDBデータベースが使用されます。これは、SQLServerインスタンスの心臓部のようなものです。実際には、TempDBデータベースなしでは作業できません。

    SQLServerがTempDBを使用する操作の概要を簡単に説明します。

    • OrderbyおよびGroupby句
    • インデックスの作成とオンラインインデックスの再構築
    • Tempテーブルとテーブル変数のストレージはTempDBデータベースにあります。
    • スナップショットアイソレーションと読み取りコミットスナップショットアイソレーション
    • DBCCコマンド
    • ハッシュは静的カーソル、長時間実行トランザクションを結合します。
    • XMLクエリ
    • SQLServerデータベースエンジンによって作成された内部オブジェクト。
    • バージョンストア
    • 複数のアクティブレコードセット(MARS)

    TempDBの詳細については、この記事をご覧ください。

    SQL Serverは、データベースエンジンサービスの再起動時にこのTempDBデータベースを再作成します。この再起動は、SQLサービスの自動または手動の再起動が原因である可能性があります。 sys.databasesにクエリを実行して、データベースサービスの起動時刻でもあるTempDBの作成日を表示できます。

    SELECT create_date AS 'SQL Service Startup Time'
    FROM sys.databases
    WHERE name = 'tempdb';

    TempDBSQLServerデータベースの構成とベストプラクティス

    時々、TempDBデータベースの予期しない成長に気付くことがあります。これを回避するための最初のステップは、ベストプラクティスに従って構成することです。このセクションでは、TempDB構成がSQLServerのさまざまなバージョンであることを確認しましょう。

    さらに大きくなる複数のDATAファイル用にTempDBを構成する

    ベストプラクティスに従って、すべてのファイルが均等に増加する複数のデータファイルが必要です。ファイルの数は、論理プロセッサによって異なります。

    プロセッサ

    TempDBデータファイルの数

    8以下の論理プロセッサ

    8

    8を超える論理プロセッサ

    8つのデータファイルから始めます。

    データファイルを4の倍数に増やし、TempDBの競合についてパフォーマンスカウンターを監視します。

    2016より前のバージョンのSQLServerの場合、インストールプロセス中に使用できる構成はありません。

    デフォルトでは、次の構成で1つのデータとログファイルのみが作成されます。

    TempDBプライマリファイル

    データファイルを10%自動拡張(ディスクがいっぱいになるまで)

    TempDBログファイル

    データファイルを10%自動拡張します(ディスクがいっぱいになるか、最大ログファイルサイズが2 TBに達するまで)

    SQL Server 2014 TempDBSQLServerデータベースの構成

    SQL Server 2016は、ベストプラクティスに従って、インストールプロセス中にTempDB構成の拡張機能を提供します。

    TempDBプライマリおよびセカンダリファイル

    64 MBの自動拡張(ディスクがいっぱいになるまで)

    TempDBログファイル

    64 MBの自動拡張(ディスクがいっぱいになるか、最大ログファイルサイズが2 TBに達するまで)

    SQLServer2016以降のTempDB構成

    不均一な自動拡張SQLServerデータベースTempDB

    SQL Serverは、ラウンドロビン方式を使用して、同じサイズでない複数のデータファイルを埋めます。 1つのファイルが大きくなることがありますが、他のファイルは最小限の成長のままです。不均一なファイルの場合、SQL Serverはほとんどのクエリに大きなファイルを使用し、それは成長し続けます:

    1. 同じ自動拡張のTempDBファイルを使用します(前のポイントで説明したように)。
    2. データベース内のすべてのデータファイルを一緒に拡張するためのトレースフラグ1117を有効にします。

    2番目のポイントはSQLServer2016以降で自動的に修正されますが、以前のバージョンでは有効にする必要があります。 SQLServer2016以降ではこのトレースフラグは必要ありません。

    TempDBの成長シナリオ

    このセクションでは、SQLServerデータベースのTempDBの拡張に関するいくつかのシナリオを示します。私のSQLインスタンスには、次の構成の8つのデータファイルがあります。

    次に、次のクエリを実行して一時テーブルを作成し、データの挿入を実行します。一時テーブルの保存場所はTempDBデータベースです。このクエリは、複数の列を持つCROSS JOIN演算子を使用し、ORDERBY句を使用して結果をさらに並べ替えます。

    注: 本番システムではこのクエリを実行しないでください。デモ目的でのみ使用しています。

    SELECT *
    FROM sys.configurations
    CROSS JOIN sys.configurations SCA
    CROSS JOIN sys.configurations SCB
    CROSS JOIN sys.configurations SCC
    CROSS JOIN sys.configurations SCD
    CROSS JOIN sys.configurations SCE
    CROSS JOIN sys.configurations SCF
    CROSS JOIN sys.configurations SCG
    CROSS JOIN sys.configurations SCH
    ORDER BY SCA.name,
    SCA.value,
    SCC.value_in_use DESC;

    このクエリには時間がかかり、システムでもCPU使用率が高くなる可能性があります。クエリの実行中に、別のクエリウィンドウを開き、DMVsys.dm_db_task_space_usageを使用しての情報を取得します。 タスクによるページ割り当てと割り当て解除アクティビティ。このDMVを他のDMVと結合して、SQLServerデータベースTempDBに必要な情報を取得します。

    SELECT s.session_id, dbu.database_id
    , dbu.internal_objects_alloc_page_count, dbu.internal_objects_dealloc_page_count
    , (dbu.internal_objects_alloc_page_count - dbu.internal_objects_dealloc_page_count) * 8192 / 1024 kbytes_used_internal
    , r.total_elapsed_time
    FROM sys.dm_Exec_requests r
    INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
    LEFT JOIN sys.dm_db_task_space_usage dbu ON dbu.session_id = r.session_id
    AND dbu.request_id = r.request_id
    WHERE internal_objects_alloc_page_count > 0
    ORDER BY kbytes_used_internal DESC;
    出力には、セッションID 55の内部オブジェクトページ数とそのサイズ(kbytes_used_internal)が表示されます。SQLServerクエリオプティマイザーは、このクエリを並列モデルで実行します。したがって、出力に複数のセッションID71が表示されます。

    推定実行プランを表示することもできます。以下に示すように、2つのコストのかかるオペレーターを取得します。

    • 並列処理:47.3%
    • 並べ替え:52.3%

    並べ替え演算子では、推定演算子コストが138,576.5と高いことがわかります:

    次のクエリはDMVsys.dm_db_file_space_usageを使用します sys.master_filesと結合して、クエリの実行中にSQLServerデータベースTempDBの割り当て済みおよび未割り当てのエクステントページ数を確認します。

    select mf.physical_name, mf.size as entire_file_page_count,
    dfsu.unallocated_extent_page_count,
    dfsu.user_object_reserved_page_count,
    dfsu.internal_object_reserved_page_count,
    dfsu.mixed_extent_page_count
    from sys.dm_db_file_space_usage dfsu
    join sys.master_files as mf
    on mf.database_id = dfsu.database_id
    and mf.file_id = dfsu.file_id

    クエリの実行とTempDBデータベースでの使用状況を監視し、必要に応じてプロセスを強制終了してスペースをすぐに解放できます。また、TempDBの大幅な増加を引き起こすクエリを最適化する必要があります。

    拡張イベントを使用してSQLServerデータベースのTempDBの使用状況を監視する

    拡張イベントは、TempDBデータベースの監視に役立ちます。クエリを使用して、次の拡張イベントを追加できます。

    • database_file_size_change
    • databases_log_file_used_size_changed

    拡張イベントの作成

    CREATE EVENT SESSION [TempDB Usage] ON SERVER
    ADD EVENT sqlserver.database_file_size_change(

    ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text)),
    ADD EVENT sqlserver.databases_log_file_used_size_changed(

    ACTION(sqlserver.client_hostname,sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text))
    ADD TARGET package0.event_file(SET filename=N'TempDBUsage',max_rollover_files=(0))
    WITH (STARTUP_STATE=OFF)
    GO

    拡張イベントセッションを開始する

    ALTER EVENT SESSION [TempDBTest] ON SERVER STATE = START;

    次に、ワークロードを実行してTempDBデータベースを使用し、データファイルを拡張します。拡張イベントは、データファイルの増加と、この増加の原因となったクエリをキャプチャします。

    拡張イベントセッションファイルをSSMSGUIモードで表示するか、次のクエリを使用してTempDBの成長を監視できます。

    TempDBの成長を監視する

    SELECT [eventdata].[event_data].[value]('(event/action[@name="session_id"]/value)[1]', 'INT') AS [SessionID],
    [eventdata].[event_data].[value]('(event/action[@name="client_hostname"]/value)[1]', 'VARCHAR(100)') AS [ClientHostName],
    DB_NAME([eventdata].[event_data].[value]('(event/action[@name="database_id"]/value)[1]', 'BIGINT')) AS [GrowthDB],
    [eventdata].[event_data].[value]('(event/data[@name="file_name"]/value)[1]', 'VARCHAR(200)') AS [GrowthFile],
    [eventdata].[event_data].[value]('(event/data[@name="file_type"]/text)[1]', 'VARCHAR(200)') AS [DBFileType],
    [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') AS [EventName],
    [eventdata].[event_data].[value]('(event/data[@name="size_change_kb"]/value)[1]', 'BIGINT') AS [SizeChangedKb],
    [eventdata].[event_data].[value]('(event/data[@name="total_size_kb"]/value)[1]', 'BIGINT') AS [TotalSizeKb],
    [eventdata].[event_data].[value]('(event/data[@name="duration"]/value)[1]', 'BIGINT') AS [DurationInMS],
    [eventdata].[event_data].[value]('(event/@timestamp)[1]', 'VARCHAR(MAX)') AS [GrowthTime],
    [eventdata].[event_data].[value]('(event/action[@name="sql_text"]/value)[1]', 'VARCHAR(MAX)') AS [QueryText]
    FROM
    (
    SELECT CAST([event_data] AS XML) AS [TargetData]
    FROM [sys].[fn_xe_file_target_read_file]('C:\TEMP\TempDBusage*.xel', NULL, NULL, NULL)
    ) AS [eventdata]([event_data])
    WHERE [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'database_file_size_change'
    OR [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(100)') = 'databases_log_file_used_size_changed'
    AND [eventdata].[event_data].[value]('(event/@name)[1]', 'VARCHAR(MAX)') <> 'databases_log_file_used_size_changed'
    ORDER BY [GrowthTime] ASC;

    スナップショットアイソレーション

    クエリにスナップショットアイソレーションを使用する場合があります。この分離モデルでは、SQLServerは各トランザクションの更新された行バージョンをTempDBに格納します。大規模または長時間実行されるトランザクションの場合、巨大なTempDBデータベースを見ることができます。

    SETコマンドを使用してトランザクションを実行し、スナップショットアイソレーションを指定できます。

    SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
    BEGIN TRAN;
    UPDATE [AdventureWorks].[Person].[Person]
    SET
    [Title] = 'Mr.';
    COMMIT TRAN;

    sys.databasesにクエリを実行することもできます システムビューを使用して、ユーザーデータベースにスナップショットアイソレーションがあるかどうかを確認します。

    AdventureWorksデータベースでスナップショットアイソレーションを有効にするクエリ

    ALTER DATABASE AdventureWorks
    SET ALLOW_SNAPSHOT_ISOLATION ON
    GO

    スナップショットアイソレーションを使用してユーザーデータベースをチェックするクエリ

    SELECT *
    FROM sys.databases
    WHERE(snapshot_isolation_state = 1
    OR is_read_committed_snapshot_on = 1)
    AND database_id > 4;

    次のスクリーンショットでは、AdventureWorksデータベースにスナップショットアイソレーションがあることがわかります。 TempDBデータベースにもスナップショットアイソレーションがありますが、クエリでは、4未満のdatabase_idをスキップしました:

    DMV sys.dm_db_file_space_usageを使用して、TempDBのバージョンストアを監視できます。

    SELECT GETDATE() AS runtime,
    SUM(user_object_reserved_page_count) * 8 AS usr_obj_kb,
    SUM(internal_object_reserved_page_count) * 8 AS internal_obj_kb,
    SUM(version_store_reserved_page_count) * 8 AS version_store_kb,
    SUM(unallocated_extent_page_count) * 8 AS freespace_kb,
    SUM(mixed_extent_page_count) * 8 AS mixedextent_kb
    FROM sys.dm_db_file_space_usage;

    ここでは、バージョンストアのサイズが67968KBであることがわかります。大規模または長時間実行されるトランザクションの場合、このバージョンストアが原因でSQLServerデータベースのTempDBサイズが巨大になることがあります。

    バージョンストアのサイズが非常に大きくなる可能性があるもう1つのケースは、常に読み取り専用のセカンダリレプリカです。セカンダリデータベースでクエリを実行すると、スナップショットアイソレーションレベルが自動的に使用されます。ご存知のように、スナップショットアイソレーションレベルはTempDBの行バージョンをコピーします。

    次のperfmonカウンターを監視する必要があります。

    • SQLServer:Transactions \ Longest Transaction Running Time – 最も拡張されたアクティブなトランザクションをキャプチャします。
    • SQLServer:Transactions \ Versionストアサイズ(KB) –TempDB内のすべてのバージョンストアの現在のサイズをキャプチャします。
    • SQLServer:Transactions \ Version Cleanup rate(KB / s )–このカウンターを使用して、TempDBでのバージョンクリーンアップの速度を表示できます
    • SQLServer:Transactions \ Version Generation rate(KB / s) –このカウンターを使用してバージョンストアのキャプチャレートをキャプチャできます。

    セカンダリデータベースのAlwaysonでも、バージョン管理のためにTempDBの増加を監視する必要があります。長時間実行されているセッションを強制終了して、TempDBデータベースのバージョン管理と再利用スペースをクリアできるようにします。

    結論

    この記事では、SQL ServerデータベースのTempDBデータベースのベストプラクティスと、予期しない成長を検出して防止するためのさまざまな方法について学習しました。 TempDBを定期的に監視し、さまざまなアラートを事前に設定する必要があります。

    • TempDBサイズの監視
    • ドライブスペースの監視
    • 長期にわたるトランザクション


    1. MountainLionにpggemをインストールできません

    2. WHERE句のCAST(DATETIME AS DATE)

    3. MySQL複数の値のように

    4. OPENROWSETクエリでの変数の使用