SE の雑記

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

SQL Server のゴーストクリーンアップタスクの基本動作 その 3

leave a comment

ゴーストクリーンアップタスクの続きです。
# 微妙にゴーストレコードについておっているような気がしてきましたが、そこはスルーで。

■PFS からゴーストレコードを見てみる


ゴーストレコードがどれぐらい存在するかを見る方法として

  1. DBCC PAGE で、データページ or インデックスページを確認
  2. sys.dm_db_index_physical_stats
  3. DBCC PAGE で PFS を確認

というような方法があります。

DBCC PAGE で、データファイルまたは、インデックスページを確認するのは今までの投稿で使用してきた方法になります。

ゴーストレコードが存在している場合は対象のページにヘッダ情報が

m_slotCnt = 10
m_ghostRecCnt = 5

というようになります。
上記の情報であれば、ページ内に 10 レコード存在しいていて、そのうち 5 レコードがゴーストレコードということになります。

対象のスロットの情報を見ると

lot 0 Offset 0x60 Length 743
Record Type = GHOST_DATA_RECORD     Record Attributes =  NULL_BITMAP    Record Size = 743

Record Type が [GHOST_DATA_RECORD] となっているからスロットのレコードはゴーストレコードとなっていることが確認できます。

動的管理ビューの sys.dm_db_index_physical_stats を参照することでゴーストレコードを確認することもできます。

SELECT
    OBJECT_NAME(object_id) object_name,
    index_id,
    index_type_desc,
    alloc_unit_type_desc,
    index_level,
    record_count,
    ghost_record_count
FROM
    sys.dm_db_index_physical_stats(DB_ID(N’TEST’), OBJECT_ID(N’dbo.Table_1′), NULL, NULL, ‘DETAILED’)

image

動的管理ビューから見る場合は、モードとして、[SAMPLED] か [DETAILED] を使用する必要があります。

[LIMITED} を使用した場合は、リーフノードのスキャンはされない (中間ノードのみスキャンをして断片化の情報を取得) ため、ゴーストレコードの件数が表示されません。
image

sys.dm_db_index_physical_stats はインデックスの断片化情報を取得するために使用しますが、レコード数が多いとかなり時間がかかるので気軽に実行でき無いこともしばしば。

それでは、今回の本題である PFS からゴーストレコードを見ていきたいと思います。

最初の PFS は 1 ページ目にありますので、DBCC PAGE は以下のコマンドになります。

DBCC TRACEON(3604)
DBCC PAGE(N’TEST’, 1, 1, 3)
DBCC TRACEOFF(3604)

先ほどのページヘッダは [323] ページを見ていました。

323 ページの PFS の情報 ((1:322)      – (1:323)) は以下のようになっています。
# 322 / 323 ページの情報となっています。

(1:313)      – (1:319)      = NOT ALLOCATED   0_PCT_FULL                             
(1:320)      – (1:321)      = NOT ALLOCATED   0_PCT_FULL Has Ghost
(1:322)      – (1:323)      =     ALLOCATED   0_PCT_FULL Has Ghost
(1:324)      – (1:342)      =     ALLOCATED   0_PCT_FULL
(1:343)      -              = NOT ALLOCATED   0_PCT_FULL                             

[ALLOCATED] [HasGhost] となっていますね。
この情報から割り当て済みのページでゴーストレコードが含まれていることが分かります。

322 / 323 ページのヘッダ情報を確認してみます。

[322 ページ]
m_slotCnt = 10
m_ghostRecCnt = 10

[323 ページ]
m_slotCnt = 10
m_ghostRecCnt = 5

[(1:320)      – (1:321)] は [NOT ALLOCATED] [Has Ghost] となっています。
ではこのページのヘッダ情報も確認をしておきます。

[320 ページ]
m_slotCnt = 1
m_ghostRecCnt = 1

[321 ページ]
m_slotCnt = 1
m_ghostRecCnt = 1

NOT ALLOCATED でゴーストレコードが 1 レコード残っていますが [NOT ALLOCATED] となっているので再利用時に初期化されて使用されるようです。

[DBCC CLEANPAGE] を使用してページをクリーニングすることでこのようなページを明示的に初期化することができます。

DBCC CLEANPAGE(5, 1, 320)
DBCC CLEANPAGE(5, 1, 321)

クリーニングを実行することで [m_slotCnt]
[m_ghostRecCnt] が [0] となります。
PFS の情報は、[NOT ALLOCATED] [Has Ghost] のまま変わらないようですが。

この状態で [DBCC FORCEGHOSTCLEANUP] を実行してその後 PFS を確認します。

(1:320)      – (1:322)      = NOT ALLOCATED   0_PCT_FULL Has Ghost
(1:323)      – (1:342)      =     ALLOCATED   0_PCT_FULL
(1:343)      -              = NOT ALLOCATED   0_PCT_FULL                             

323 ページの PFS の情報が [ALLOCATED] に変わっていますね。
ゴーストレコードがなくなったので、[Has Ghost] が消えています。
# 322 ページに関しては 1 レコード、ゴーストレコードが残っているので [Has Ghost] になっています。ゴーストクリーンアップタスクの実行時にページ内の全スロットがゴーストレコードになっている場合このような PFS の状態になるみたいですが。

 

それでは最後に [sys.dm_db_index_physical_stats] と [DBCC PAGE] で PFS を表示した際のメモリ上のデータの件数の違いを確認してみたいと思います。
10 万レコード格納した状態でデータを取得しています。

SELECT
    page_type,
    page_level,
    SUM(row_count) as row_count,
    COUNT(*) as page_count
FROM
    sys.dm_os_buffer_descriptors
WHERE
    database_id = DB_ID()
GROUP BY
    page_type,
    page_level
ORDER BY
    page_type

[sys.dm_db_index_physical_stats]
image

[DBCC PAGE]
image

[sys.dm_db_index_physical_stats] で [DETAILED] を使用して断片化を確認した場合は、リーフノードのスキャンを行いますのでデータが格納されているページがスキャンされます。

PFS の場合は、ファイルヘッダーページをはじめとして、最小限のページがスキャンされますので、読み込まれるページ数には大きな差があります。
軽く現状を確認したいということであれば [PFS] を確認するのが良さそうですね。

ゴーストクリーンアップタスクに関してはまだ書けることがありますのでこのシリーズはもうちょっと続きます。

Share

Written by Masayuki.Ozawa

4月 9th, 2011 at 10:49 pm

Posted in SQL Server

Tagged with

Leave a Reply