元のソース: ファーストラインのコードファーマー
http://www.open-open.com/lib/view/open1427267261293.html
非クラスター化インデックス。これは誰もがよく知っていることであり、ビジネス上の理由からSQLを非常に複雑に記述し、多くのテーブルを結合し、その後、突然破裂する必要があります。。。現時点では、DBAまたは上級開発者が、この面倒なSQLを実行計画の分析を通じて紹介します。。。多分あなたはあなたが持ってはならないテーブルスキャンを見ることができます。。。すべての悪の源。。。次に、非クラスター化インデックスをキーフィールドに追加します。。。速度がアストンマーティンよりも速いことを見つけるだけです。。。次に、なぜ非クラスタ化インデックスが非常に高速になるのかという疑問が生じます。。。どうやって???とても気になりますか???
この記事では、謎を解明しましょう。
1:現象
まず、非クラスター化インデックスの真の内容を見て、実行プランでどのように見えるかを見てみましょう。。。次の図のように、ここに製品テーブルがあり、8wを超えるデータが入力されてから、[名前]列に非クラスター化インデックスを設定しました。
上の写真から、見てみたい「インデックス検索【非クラスター化]」という面白いものが2つ見られましたが、これは皆さんにもお馴染みで、言いたいことです。一見したところ、これはなんてことなのでしょう。。。非クラスター化インデックスとそれの関係は何ですか???
2:RIDとは
以前の記事を通して、データページでレコードを見つける方法を誰もが知っていると思いますか?シークレットはスロット内のオフセットによって決定され、次に質問が来ます。データページレベルに上昇した場合、(pageID:slotID)だけでレコードを見つけることができます。ファイルレベルを上げる場合、データページでレコードを見つけるために(fileID:pageID:slotID)を知る必要があるだけですか?実際、ここでのRIDは、ファイルの高さで(fileID:pageID:slotID)を介してテーブルレコードを見つけることです。。。両方を表示する必要がある場合は、RID = RowID =(fileID:pageID:slotID)
正直に言うと、lは実際にそのような関数(sys.fn_PhysLocFormatter(%% physloc %%))をsqで提供しています。次の図を見てください。
上記の画像を見ると、たとえば、製品ID = 18088のレコードが一見してとても興奮していますが、ファイル1、34941データページ、スロット0、製品ID = 18089にあります。
それはスロット1にあります。さて、RIDが何であるかを知っていると、非クラスター化インデックスを完全に理解するのにそれほど遠くないと思います。。。
3つ:非クラスター化インデックス
非クラスタ化インデックスを使用すると、検索を高速化できることを知っておく必要があります。テーブルスキャンの速度が同じ場合、インデックスの目的は失われます。高速化できるため、クラスタ化インデックスのように最下層で再生されるためです。 Bツリーが作成されます。最初にサンプルデータを挿入します。
DROP TABLE dbo.Person
CREATE TABLE Person(ID INT IDENTITY,NAME CHAR(900))
CREATE INDEX idx_Person_Name ON dbo.Person(Name)
DECLARE @ch AS INT=97
WHILE @ch<=122
BEGIN
INSERT INTO dbo.Person VALUES(REPLICATE(CHAR(@ch),5))
SET @ch=@ch+1
END
上記のSQLでは、Name列を意図的にインデックスの上限でもある900文字に設定しましたが、この場合、DBCCは多くのデータページとインデックスページをエクスポートできます。
ご覧のとおり、dbcc indを実行すると、Personテーブルに既に4つのデータページと5つのインデックスページがあることがわかりました。このうち、データページ151はテーブルトラッキングページであり、番号174はインデックストラッキングページです。インデックスを作成した後、エンジンは、作成したNameインデックスを格納するための特別なインデックスページを割り当てました。次に、これらのインデックスに格納されている内容を確認します。これが私が非常に心配しています。次に、No。173をエクスポートします。索引ページ。
DBCC PAGE(Ctrip,1,173,1)
Slot 0, Offset 0x60, Length 912, DumpStyle BYTE Record Type = INDEX_RECORD Record Attributes = NULL_BITMAP Record Size = 912 Memory Dump @0x000000000EF1C060 0000000000000000: 16616161 61612020 20202020 20202020 †.aaaaa 0000000000000010: 20202020 20202020 20202020 20202020 † 0000000000000020: 20202020 20202020 20202020 20202020 † 0000000000000030: 20202020 20202020 20202020 20202020 † 0000000000000040: 20202020 20202020 20202020 20202020 † 0000000000000050: 20202020 20202020 20202020 20202020 † 0000000000000060: 20202020 20202020 20202020 20202020 † 0000000000000070: 20202020 20202020 20202020 20202020 † 0000000000000080: 20202020 20202020 20202020 20202020 † 0000000000000090: 20202020 20202020 20202020 20202020 † 00000000000000A0: 20202020 20202020 20202020 20202020 † 00000000000000B0: 20202020 20202020 20202020 20202020 † 00000000000000C0: 20202020 20202020 20202020 20202020 † 00000000000000D0: 20202020 20202020 20202020 20202020 † 00000000000000E0: 20202020 20202020 20202020 20202020 † 00000000000000F0: 20202020 20202020 20202020 20202020 † 0000000000000100: 20202020 20202020 20202020 20202020 † 0000000000000110: 20202020 20202020 20202020 20202020 † 0000000000000120: 20202020 20202020 20202020 20202020 † 0000000000000130: 20202020 20202020 20202020 20202020 † 0000000000000140: 20202020 20202020 20202020 20202020 † 0000000000000150: 20202020 20202020 20202020 20202020 † 0000000000000160: 20202020 20202020 20202020 20202020 † 0000000000000170: 20202020 20202020 20202020 20202020 † 0000000000000180: 20202020 20202020 20202020 20202020 † 0000000000000190: 20202020 20202020 20202020 20202020 † 00000000000001A0: 20202020 20202020 20202020 20202020 † 00000000000001B0: 20202020 20202020 20202020 20202020 † 00000000000001C0: 20202020 20202020 20202020 20202020 † 00000000000001D0: 20202020 20202020 20202020 20202020 † 00000000000001E0: 20202020 20202020 20202020 20202020 † 00000000000001F0: 20202020 20202020 20202020 20202020 † 0000000000000200: 20202020 20202020 20202020 20202020 † 0000000000000210: 20202020 20202020 20202020 20202020 † 0000000000000220: 20202020 20202020 20202020 20202020 † 0000000000000230: 20202020 20202020 20202020 20202020 † 0000000000000240: 20202020 20202020 20202020 20202020 † 0000000000000250: 20202020 20202020 20202020 20202020 † 0000000000000260: 20202020 20202020 20202020 20202020 † 0000000000000270: 20202020 20202020 20202020 20202020 † 0000000000000280: 20202020 20202020 20202020 20202020 † 0000000000000290: 20202020 20202020 20202020 20202020 † 00000000000002A0: 20202020 20202020 20202020 20202020 † 00000000000002B0: 20202020 20202020 20202020 20202020 † 00000000000002C0: 20202020 20202020 20202020 20202020 † 00000000000002D0: 20202020 20202020 20202020 20202020 † 00000000000002E0: 20202020 20202020 20202020 20202020 † 00000000000002F0: 20202020 20202020 20202020 20202020 † 0000000000000300: 20202020 20202020 20202020 20202020 † 0000000000000310: 20202020 20202020 20202020 20202020 † 0000000000000320: 20202020 20202020 20202020 20202020 † 0000000000000330: 20202020 20202020 20202020 20202020 † 0000000000000340: 20202020 20202020 20202020 20202020 † 0000000000000350: 20202020 20202020 20202020 20202020 † 0000000000000360: 20202020 20202020 20202020 20202020 † 0000000000000370: 20202020 20202020 20202020 20202020 † 0000000000000380: 20202020 20940000 00010000 00020000 † ...........
Row - Offset 7 (0x7) - 6480 (0x1950) 6 (0x6) - 5568 (0x15c0) 5 (0x5) - 4656 (0x1230) 4 (0x4) - 3744 (0xea0) 3 (0x3) - 2832 (0xb10) 2 (0x2) - 1920 (0x780) 1 (0x1) - 1008 (0x3f0) 0 (0x0) - 96 (0x60)
从上面至少可以发现三个有趣的现象:
<1>:173号索引页中slot0和slot1槽位指向记录的内容已经有序了,比如:aaaaa,bbbbb。。。。这样。。。。原来非聚集索引也是有序呀。。。
<2>:6161616161就是16进制的aaaaa。
9400000001000000 :这几个数字非常重要,因为是16进制表示,所以2位16进制表示一个字节,所以可以这么解释,前面4个字节表示
pageID,中间2个字节表示fileID,后面2个字节表示slot,看到这里你是不是想起了RID。。。因为RID就是这三样的组合。。。原来非聚集索引的记录存放的就是“key+RowID”呀。。。。
<3>:通过最后的槽位列表,可以得知173号索引页上存放着8条索引记录。
好了,看完了叶子节点,我们再看分支节点,也就是IndexLevel=1的那条索引数据页,也就是78号。ok,dbcc看看吧。
このリストを見ると、前の記事のクラスター化インデックスのように、その構造がクラスター化インデックスと非常に似ていますが、非クラスター化インデックスの数が多いため、脳に画像があるかどうかわかりません。 RIDのみ。。。最後に、私も絵に貢献しています。
要約すると、たとえば、非クラスター化インデックスを歩く場合、たとえば、条件がname = 'jjjjj'である場合、そのロジックは次のようになります。78番目のインデックスデータページのキーの範囲に従って、ROWIDによって79番目のインデックスに移動します。データページは、79番目のインデックスデータページでjjjjjを正常に検出しました。この時点で、jjjjjのROWIDを取り出して、テーブルデータページ内のレコードを直接検索し、最後に出力できます。。。。。これが、RID検索がブログの最初に表示される理由です。。。