Fragen zu Indizes, die Sie nicht stellen müssen

  • Tutorial


Nachdem ich 14 Fragen zu den Indizes beantwortet hatte , die Ihnen peinlich waren, hatte ich viel mehr Kommentare, Erläuterungen und Korrekturen. Das Kompilieren aus all diesen Artikeln schien ein Unterfangen mit einem Minimum an Nutzen zu sein. Ich überlegte zweimal, warum es uns überhaupt peinlich sein sollte, solche Fragen zu stellen. Schade nicht zu wissen? Gibt es eine Möglichkeit, es herauszufinden, ohne sich selbst in die Farbe zu treiben? Gibt es. Außerdem erspart er sich zahlreiche Ungenauigkeiten, auf die viele "Antworten" im Überfluss vorhanden sind. Sie werden buchstäblich jedes Byte Ihrer Basis mit Ihren Fingerspitzen fühlen.

Dazu schlage ich vor, in SQL Server "die Haube zu heben" und in die süße Welt der Hex-Dumps einzutauchen. Es könnte sich herausstellen, dass im Inneren alles viel einfacher ist, als Sie dachten.

Einen Arbeitsplatz vorbereiten


In meinen Experimenten werde ich die kostenlose SQL Server 2014 Express Edition zusammen mit dem bekannten Management Studio verwenden. Fast das gesamte erworbene Wissen ist jedoch in SQL Server 7.0 aus den neunziger Jahren verwurzelt, und es wird nicht schwierig sein, die erworbenen Kenntnisse auf alte Installationen anzuwenden.

Für die meisten Beispiele benötigen wir das aktivierte Ablaufverfolgungsflag 3604. Ich werde es nicht in jedem von ihnen duplizieren, aber ich gehe davon aus, dass es immer eingeschaltet ist. Denken Sie daran: Wenn Sie keinen Speicherauszug oder Fehler sehen, fügen Sie am Anfang Ihres Codes Folgendes hinzu:

DBCC TRACEON(3604)
GO

Einige Befehle erfordern einen expliziten Datenbanknamen. In meinem Fall ist dies "Labor". Wenn Sie einen anderen Bezeichner wählen, vergessen Sie nicht, die entsprechenden Änderungen vorzunehmen. Gleiches gilt für einige andere Bedeutungen. Beispielsweise können die physischen Adressen der Seiten durchaus unterschiedlich sein. Ich werde versuchen, Sie daran zu erinnern, aber versuchen, Ihren Finger am Puls Ihres Codes zu halten.

Serverantworten geben häufig viele Felder oder andere Daten zurück, von denen nur ein kleiner Teil von entscheidendem Interesse ist. Da dies kein SELECT-Befehl ist, ist das Anpassen der Ausgabe nicht einfach. Deshalb werde ich den Überschuss hier und da regelmäßig abschneiden. Seien Sie nicht überrascht, wenn Sie viel mehr Daten als meine sehen.

Seitenorganisation


In SQL Server besteht die Grundstruktur zum Organisieren von Daten aus einer Seite mit 8192 Bytes (8 KB oder 8 KB, wie Sie möchten). Es kann durch Angabe des Dateicodes (FID - File ID), zu dem es gehört (siehe unten in sys.database_files), und des Codes der Seite selbst (PID - Page ID) in dieser Datei angesprochen werden. Wir werden eine solche Adresse in Form von "FID: PID" aufzeichnen. Zum Beispiel würde 1: 142 eine Seite mit Code 142 in einer Datei mit Code 1 bedeuten.

SELECT FID = file_id, name, physical_name FROM sys.database_files

FID         name            physical_name
----------- --------------- -------------------
1           Lab             D:\Lab.mdf
2           Lab_log         D:\Lab_log.ldf

Seiten von sowohl gruppierten als auch regulären Indizes sind in Form von Bäumen (B-Tree) organisiert. Wie jeder Baum hat er eine Wurzel (Wurzelknoten), Blätter (Blattknoten) und Zwischenknoten (Zwischenknoten), aber wir können sie Zweige nennen, was die Pflanzenanalogie fortsetzt. Damit diese Elemente ohne Visualisierung leicht voneinander unterschieden werden können, gibt es das Konzept einer Indexebene. Nullwert bedeutet die maximale Blattzahl - die Wurzel des Baumes. Alles dazwischen ist ein Zweig.



Erstellen wir eine einfache Tabelle für 1000 Einträge mit einem Clustered-Index. Die erste Spalte ist ein einfaches Auto-Inkrement-Feld, die zweite Spalte hat denselben Wert, jedoch mit einem Minuszeichen, und die dritte Spalte ist ein Binärwert 0x112233445566778, der bequem als Markierung in einem Speicherauszug verwendet werden kann.

CREATE TABLE [dbo].[ClusteredTable] (
     [ID] [int] IDENTITY(1,1) PRIMARY KEY CLUSTERED,
     [A] AS (-[ID]) PERSISTED NOT NULL,
     [B] AS (CONVERT([binary](8), 0x1122334455667788)) PERSISTED NOT NULL
)
GO
INSERT INTO [dbo].[ClusteredTable] DEFAULT VALUES;
GO 1000

Wir werden jetzt das undokumentierte, aber unsterbliche DBCC IND-Team verwenden, um eine Seiten-Autopsie durchzuführen. Das erste Argument muss den Namen oder den Code der Datenbank angeben, in der sich die zu untersuchende Tabelle befindet. Der zweite ist der Name dieser Tabelle (oder der Code des entsprechenden Objekts), der dritte ist der Indexcode. Es gibt einen vierten optionalen Parameter - Partitionscode. Aber er interessiert uns in diesem Zusammenhang nicht, anders als der Indexcode, auf den ich noch näher eingehen werde. Der Wert 0 gibt an, dass eine Heap-Ebene angefordert wird. Im Wesentlichen handelt es sich hierbei um eine Datenschicht ohne Indizes. Der Cluster-Index ist für Nummer 1 reserviert (er wird wie in Heap zusammen mit den Daten angezeigt). In allen anderen Fällen geben Sie einfach den Code für den entsprechenden Index an. Schauen wir uns den gruppierten Index unserer Tabelle an.

Seit Version 2012 wurde die DMV-Funktion sys.dm_db_database_page_allocations hinzugefügt. Es ist etwas bequemer zu bedienen, bietet detailliertere Informationen und hat viele andere Vorteile. Alle unsere Beispiele lassen sich damit leicht reproduzieren.

DBCC IND('Lab', 'ClusteredTable', 1)
GO

PageFID PagePID     IndexID     PageType IndexLevel
------- ----------- ----------- -------- ----------
1       78          1           10       NULL
1       77          1           1        0
1       79          1           2        1
1       80          1           1        0
1       89          1           1        0
1       90          1           1        0

Als Serverantwort erhalten wir eine Liste der gefundenen Indexseiten. Die ersten Spalten sind die bekannten FID und PID, die zusammen die Seitenadresse ergeben. IndexID bestätigt erneut mit unserer Unit, dass wir mit einem Clustered-Index arbeiten. Ein Seitentyp (PageType) mit dem Wert 1 ist data, 2 ist indexiert, 10 ist IAM (Index Allocation Map), das eine indirekte Beziehung zu den Indizes hat, und wir werden es ignorieren. Ein weiterer Freund von uns ist der Indexlevel (IndexLevel). An ihrem Maximalwert sehen wir die Wurzel des Cluster-Index - Seite 1:79. Mit Nullwerten - Blätter 1:77, 1:80, 1:89, 1:90.

Seitenstruktur


Geistig können wir uns schon einen Seitenbaum vorstellen. Dies ist jedoch nur dann einfach, wenn wir zwei Ebenen haben. Und sie könnten noch viel mehr sein. Aus diesem Grund können Sie nicht darauf verzichten, die Seite selbst zu erkunden. Wir beginnen mit der Wurzel und verwenden ein anderes undokumentiertes, aber dasselbe unsterbliche Kommando - DBCC PAGE.

Als erstes Argument wird neben DBCC IND der Name oder Code der Datenbank verwendet. Als nächstes kommt ein Paar FID und PID der Seite, die Sie suchen. Mit dem letzten Wert geben wir das Ausgabeformat aus den folgenden verfügbaren Werten an:

  • 0 - nur der Titel;
  • 1 - Header, Dumps und Slot-Index;
  • 2 - Header und Full Dump;
  • 3 - Titel und maximales Detail für jeden Slot.

Um die Bedeutung einiger Begriffe nicht abstrakt zu erklären, werfen wir einen Blick auf den Root-Page-Dump (vergessen Sie nicht, Ihre Seitenadressen zu ersetzen):

DBCC PAGE('Lab', 1, 79, 2)
GO

PAGE: (1:79)
...
000000001431A000:   01020001 00800001 00000000 00000b00 00000000  ....................
000000001431A014:   00000400 78000000 6c1f8c00 4f000000 01000000  ....x...l.?.O.......
000000001431A028:   23000000 cc000000 0e000000 00000000 00000000  #...I...............
000000001431A03C:   9dcd3779 01000000 00000000 00000000 00000000  .I7y................
000000001431A050:   00000000 00000000 00000000 00000000
                                                        06000000  ....................
000000001431A064:   074d0000 00010006 44010000 50000000 01000687  .M......D...P......?
000000001431A078:   02000059 00000001 0006ca03 00005a00 00000100  ...Y......E...Z.....
000000001431A08C:   00002121 21212121 21212121 21212121 21212121  ..!!!!!!!!!!!!!!!!!!
...
000000001431BFE0:   21212121 21212121 21212121 21212121 21212121  !!!!!!!!!!!!!!!!!!!!
000000001431BFF4:   21212121 81007600 6b006000                    !!!!..v.k.`.
OFFSET TABLE:
Row - Offset                       
3 (0x3) - 129 (0x81)               
2 (0x2) - 118 (0x76)               
1 (0x1) - 107 (0x6b)               
0 (0x0) - 96 (0x60)                

In diesem Stadium möchte ich die Struktur der Seite als Ganzes anzeigen, also habe ich den größten Teil des Dumps ausgeschnitten, was keine Auswirkungen darauf hat.

Alles beginnt mit einem 96-Byte-Header, dessen Ende in der obigen Ausgabe mit einer Lücke markiert ist, um das Lesen zu erleichtern. Im Alltag ist er nicht da. Hinter der Überschrift befinden sich Datensätze mit Daten, die als "Slots" bezeichnet werden (ich habe diesen Begriff nicht übersetzt). Genauer gesagt versuchen sie, der Überschrift zu folgen. Die Daten in der Datenbank sind jedoch variable Werte. Tupel werden hinzugefügt, gelöscht, aktualisiert. Daher können sie nicht unmittelbar nach dem Header, sondern vollständig in einer chaotischen Reihenfolge mit einem Intervall nach dem Header und auch zwischen den Slots angeordnet werden.

Um ihre aktuelle Position zu kontrollieren, befindet sich ganz am Ende der Seite ein Index dieser Slots. Jedes Element benötigt zwei Bytes, speichert den Slot-Offset auf der Seite in Form von Little-Endian (dh der letzte Wert 0x6000 in unserem Dump, wir lesen Byte für Byte rückwärts - 0x0060) und sind vom Ende an nummeriert. Der letzte ist Steckplatz 0, davor ist Steckplatz 1 und so weiter. Der Index der Slots und Daten bewegt sich sozusagen von verschiedenen Seiten der Seite aufeinander zu. Die Dekodierung ihres Index erfolgt im Dump selbst nach dem OFFSET TABLE-Header. Vergleichen Sie es mit dem Indexspeicherauszug am Ende der Seite - 81007600 6b006000.



Datensatzstruktur


Schauen wir uns nun die Slots im Detail an und wenden dafür den Ausgabemodus 1 für den DBCC PAGE-Befehl an.

DBCC PAGE('Lab', 1, 79, 1)
GO

...
Slot 0, Offset 0x60, Length 11, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 11
Memory Dump @0x0000000014B1A060
0000000000000000:   06000000 074d0000 000100                      .....M.....
Slot 1, Offset 0x6b, Length 11, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 11
Memory Dump @0x0000000014B1A06B
0000000000000000:   06440100 00500000 000100                      .D...P.....
Slot 2, Offset 0x76, Length 11, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 11
Memory Dump @0x0000000014B1A076
0000000000000000:   06870200 00590000 000100                      .?...Y.....
Slot 3, Offset 0x81, Length 11, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 11
Memory Dump @0x0000000014B1A081
0000000000000000:   06ca0300 005a0000 000100                      .E...Z.....
...

Dies sind die gleichen vier Slots, die wir zuvor gesehen haben, nur ihre binäre Darstellung ist aus dem Seiten-Dump herausgeschnitten und wird auf einem Silbertablett serviert, was unsere weitere Untersuchung offensichtlich erleichtern wird.

Das erste Byte von jedem von ihnen (0x06) enthält Informationen über den Typ des Datensatzes. Genauer gesagt sind nur die Bits 1-3 dafür verantwortlich (in unserem Fall 011b = 3), die einen der folgenden Werte annehmen können:

  1. 0 - Daten;
  2. 1/2 - weitergeleitete / weitergeleitete Datensätze;
  3. 3 - Index;
  4. 4 - Binärdaten (Blob);
  5. 5/6/7 - Ghost-Einträge für Index / Daten / Versionen.

Da in unseren Tests das Nullbit nicht gesetzt wird, können wir mit Sicherheit sagen, dass der Datensatz den Index beschreibt, wenn der niederwertigste Teil des Bytes 0x06 ist.

In unserem Fall folgt auf das erste Byte der Schlüsselwert, aus dem der Clusterindex aufgebaut ist, und danach die Seitenadresse in einem leicht invertierten PID: FID-Format. Das heißt, für Steckplatz 3 lautet der Schlüssel-ID-Wert 0xca030000 (970 dezimal nach dem Little-Endian-Flip), PID - 0x5a000000 (90), FID - 0x0100 (1). Was kann übersetzt werden mit: "Um nach Datensätzen mit IDs von 970 zu suchen, gehen Sie zu Seite 1:90." Für Steckplatz 2 erhalten wir ID = 0x87020000 (647), PID = 59000000 (89), FID = 0x0100 (1). Und wir lesen: "Informationen zu Datensätzen mit IDs von 647 bis 970 (die bereits von Steckplatz 3 bereitgestellt werden) finden Sie auf Seite 1:89." Und so senden uns alle vier Slots vier Seiten, jede für ihren eigenen Wertebereich. Wir haben diese vier Seiten bereits zu Beginn gesehen, als wir spekulativ einen Baum nach der Liste der Seiten gebaut haben. Schauen Sie sich die allererste Ausgabe des DBCC IND-Befehls an.

Wenn unsere Tabelle viel größer wäre, würden diese Datensätze auf die Indexseite der Zwischenebene verlinken (Indexebene der Wurzel minus einer Ebene). Wenn wir beispielsweise nach dem Wert ID = 743794 suchen, erhalten wir auf der Stammseite einen Steckplatz, der für einen ziemlich großen Bereich von 700000-750000 verantwortlich ist. Er würde uns zu einer ähnlichen Seite senden, mit der Ausnahme, dass wir dort den Suchbereich auf die Positionen 743000-744000 einschränken würden. Was wiederum würde bereits an die Datenseite senden, wo Datensätze 743750-743800 gespeichert sind.



Sobald wir über Daten sprechen, gehen wir zur Seite 1:89, auf der Werte von 657 bis 970 angezeigt werden, die wir gerade entdeckt haben.

DBCC PAGE('Lab', 1, 89, 1)
GO

...
Slot 0, Offset 0x60, Length 23, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 23
Memory Dump @0x0000000011F1A060
0000000000000000:   10001400 87020000 79fdffff 11223344 55667788  ....?...yyyy."3DUfw.
0000000000000014:   030000                                        ...  
Slot 1, Offset 0x77, Length 23, DumpStyle BYTE
Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 23
Memory Dump @0x0000000011F1A077
0000000000000000:   10001400 88020000 78fdffff 11223344 55667788  ........xyyy."3DUfw.
0000000000000014:   030000                                        ...   
...

Die Datenseite unterscheidet sich nicht wesentlich von den Seiten mit dem Index. Dies ist immer noch der gleiche Titel und die gleichen Slots mit ihrem Index am Ende der Seite. Ich habe mich zum Beispiel auf einige der ersten Datensätze beschränkt, deren Dump wir nacheinander durchgehen werden.

  1. 0x10. Die Art der Aufzeichnung, mit der Sie bereits vertraut sind. Die Bits 1-3 geben den Wert 0 an, was auf eine Datenseite hinweist. Das gesetzte Bit 4 wird jedoch weiterhin angezeigt und signalisiert, dass der Datensatz eine NULL-BITMAP hat - eine Bitmap, bei der jedem Feld der untersuchten Tabelle ein Bit zugewiesen ist. Wenn dieses Bit gesetzt ist, wird davon ausgegangen, dass der Wert im entsprechenden Feld NULL ist.
  2. 0x00. Das zweite Byte ist ab SQL Server 2012 für knifflige Einträge mit Geisterweiterleitung verantwortlich, und wir sind jetzt nicht daran interessiert.
  3. 0x1400. Alle Typen können in Typen mit fester Länge und variabler Länge eingeteilt werden. Die offensichtlichsten Beispiele sind Binary (n) und Varbinary (n). Unmittelbar danach werden die Daten direkt an Daten mit Typen fester Länge übergeben. Und es zeigt selbst an, bei welchem ​​Versatz in dem Schlitz die nächste Information beginnt. Der angegebene Wert (nämlich 20 in Dezimalzahl nach einer Umkehrung von Little-Endian) = 2 (erste Bytes mit Typen) + 2 (diese Bytes) + 4 (Bytes für int-Typ im ID-Feld) + 4 (Bytes für denselben Typ in Feld A) + 8 (Bytes pro Binärfeld B).
  4. 0x87020000 / 88020000 sind die Werte von 647 und 648, die keine anderen als die Werte des ID-Felds sind. Denken Sie daran, bevor wir geschrieben haben, dass Slot 2 Datensätze liefert, beginnend mit ID = 647. Dies ist, was sie sind.
  5. 0xFFFFFD79 / 0xFFFFFD78 - und das ist der Wert des Feldes "A" (-647, -648), den wir mit der Formel -ID berechnet haben.
  6. 0x11223344 55667788 - Unser binärer Marker, den wir für Feld B definiert haben, vervollständigt den Datenteil logisch
  7. 0x0300 - die Anzahl der Spalten. Wie erwartet gibt es drei davon (ID, A, B).
  8. 0x00 - und das ist die gleiche NULL-BITMAP, die ich zuvor erwähnt habe. Ihre Länge ist abhängig von der Anzahl der Spalten (jeweils ein Bit) und wird auf das nächste Byte gerundet. In unserem Fall reicht ein Byte aus, um drei Bits (für drei Felder ID, A, B) zu speichern. Da wir keine NULL-Werte haben, werden alle Bits zurückgesetzt.


Regelmäßige Indizes


Nun erstellen wir einen regulären, nicht gruppierten Index in Feld A in unserer Tabelle und sehen, wie er sich vom gruppierten unterscheidet.

CREATE INDEX
     [IX_ClusteredTable]
ON [dbo].[ClusteredTable] (
     [A] ASC
)
GO

Mal sehen, welche Seiten betroffen waren und dazu geben wir den Code des neuen Index - 2 an.

DBCC IND('Lab', 'ClusteredTable', 2)
GO

PageFID PagePID     IndexID     PageType IndexLevel
------- ----------- ----------- -------- ----------
1       94          2           10       NULL
1       93          2           2        0
1       118         2           2        0
1       119         2           2        1

Sehr bekanntes Bild. Es gibt Seiten auf Blattebene, die wir an IndexLevel = 0 erkennen. Erst jetzt haben sie den Typ PageType = 2, das heißt, es handelt sich um Indexseiten und nicht um Datenseiten. Es gibt auch einen Wurzelknoten mit unverändertem IndexLevel = 1, PageType = 2. Unter der Adresse 1: 119 werden wir weiter forschen.

DBCC PAGE('Lab', 1, 119, 1)
GO

Slot 0, Offset 0x60, Length 15, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 15
Memory Dump @0x000000001095A060
0000000000000000:   0618fcff ffe80300 005d0000 000100             ..uyye...].....
Slot 1, Offset 0x6f, Length 15, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =                 Record Size = 15
Memory Dump @0x000000001095A06F
0000000000000000:   065afeff ffa60100 00760000 000100             .Z?yy¦...v.....

Und wieder nichts grundsätzlich Neues. Immer der gleiche Titel, die gleichen Slots. Sind dies die beiden Slots, die auf die beiden oben gefundenen Seiten (1:93, 1: 118) verweisen? Stellen wir es in die Regale. Das erste Byte mit dem Typ 0x06 besagt, dass es sich um einen Index handelt. Die letzten 6 Bytes sind PID: FID, die wir bereits analysieren können. Nach der Umwandlung in das vertraute Format erhalten wir genau 1:93 (0x5d000000 0100) und 1: 118 (0x7600000000 0100). Aber dazwischen erwartet uns eine interessante Überraschung. Für Steckplatz 1 sind die Werte 0x5AFEFFFF und 0xA6010000 beispielsweise nicht mehr als -422 und 422. Zusätzlich zum Wert von Feld A, den wir in den Index aufgenommen haben, enthält es auch den Wert der Cluster-Schlüssel-ID.

Der Rest des Schemas ähnelt dem im Clusterindex. Der Bereich von -1000 bis -422 wird von Seite 1:93 bedient, von -422 wird von Seite 1: 118 bedient. Mit Ausnahme der Tatsache, dass der gruppierte Index hier auf Datenseiten verweist, und wohin führt dieser? Lass uns sehen.

DBCC PAGE('Lab', 1, 118, 1)
GO

...
m_pageId = (1:118)                  m_headerVersion = 1                 m_type = 2
...
Slot 0, Offset 0x60, Length 12, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 12
Memory Dump @0x000000001331A060
0000000000000000:   165afeff ffa60100 00020000                    .Z?yy¦......
Slot 1, Offset 0x6c, Length 12, DumpStyle BYTE
Record Type = INDEX_RECORD          Record Attributes =  NULL_BITMAP    Record Size = 12
Memory Dump @0x000000001331A06C
0000000000000000:   165bfeff ffa50100 00020000                    .[?yy?......
...

Ich habe absichtlich eine Zeile vom Titel weggelassen, damit wir wieder davon überzeugt sind, dass uns das Schicksal auf die Indexseite geführt hat (Seitentyp m_type = 2). Sie haben den Rest wahrscheinlich als Witz gelesen. Auch der neue Datensatztyp sollte nicht verwirren - 0x16, da er 0x10 + 0x06 ist. Der erste Term ist Bit 4 des Vorhandenseins von NULL_BITMAP, das wir auf den Datenseiten gesehen haben. Der zweite ist der Indextyp.

Ihnen folgen sicher die Werte -422 (0x5AFEFFFF für Steckplatz 0) und -421 (0x5BFEFFFF für Steckplatz 1) aus Spalte A. Wir glauben, dass die vorherige Indexstufe besagt, dass Seite 1: 118 von -422 abläuft. Auf diese Werte folgen Cluster-Schlüssel (422, 421), die Sie ebenfalls nicht überraschen werden. Und dann - nur die Anzahl der Spalten (0x0200) und NULL_BITMAP (0x00), wie auf Datenseiten. Beachten Sie, dass es keine Links zu den Datenseiten selbst gibt.

Wussten Sie vorher, dass ein regulärer Index einen Cluster-Index durchläuft (falls es einen gibt, natürlich)? Und wenn Sie von einem großen (besonders natürlichen) Schlüssel geclustert werden, besteht dann die Gefahr, dass Sekundärindizes aufgebläht werden? Ich hoffe nicht Sowie sie nicht viel von diesem Artikel wussten, denn dann ist es gut :)

Ich würde jetzt gerne annehmen, dass Sie Aussagen mit dem Stil "Ein wichtiges Merkmal eines Clustered-Index ist, dass alle Werte in einer bestimmten Reihenfolge sortiert werden, entweder aufsteigend oder absteigend", wie am Anfang des Artikels erwähnt. Da wir wissen, dass die Position der Seiten unbekannt ist, dass die Reihenfolge auf der Seite durch den Index der Slots bestimmt wird, können wir nur über die Quasi-Reihenfolge sprechen. Und es ist besser, wenn sich der Clustered-Index ... Ja, er macht es perfekt. Sie wissen genau, auf welchen Seiten sich der Datencluster von X bis Y befindet.

Hoffentlich können Sie jetzt selbst mit Freude an der geleisteten Arbeit die Arbeit von Indizes mit Heap erkunden. Hier finden Sie Antworten auf die Fragen: "Ist die GUID für den Clustered-Index geeignet?", "Wie funktioniert der Seiten-Split in solchen Fällen?", "Wie sieht UNIQUIFIER aus?", "Ist Heap wirklich schneller einzufügen?" Und viele andere für sich. Zurück zum Titel des Artikels: "Sie müssen sie nicht fragen."

Bis bald unter der Haube, ich hoffe, Ihnen gefällt dieser Prozess.

Jetzt auch beliebt: