RID vs INCLUDE auf einem großen Feld

7

Ich habe eine Tabelle, in der Notizen gespeichert sind

create tblNote(  
  Id int identity(1,1),  
  ParentId  int ,   
  ParentType varchar(32),   
  NoteType varchar(32),   
  Note varchar(max),  
  CreatedBy varchar(25),   
  CreatedDate  datetime,   
  .  
  .  
  .  
  <other metadata about the note>  
)  

Ich habe in letzter Zeit viel darüber gelesen, wie MSSS mit Indizes umgeht (2005 und später).

Ich habe einen Clustered-Index für ID

[Ich habe überlegt, den Clustered-Index in parentId, parentType zu ändern, da dieser relativ eng und statisch ist. ]]

Der überwiegende Prozentsatz der Abfragen für diese Tabelle wird im Sinne von erfolgen

select NOTE, createdDate, createdBy 
from tblNote 
where parentId = 12 and parentType = 'RFQ'

Die Frage, die ich heute stellen möchte (obwohl jedes Feedback willkommen ist), lautet:

Der NC-Index, den ich hinzufügen könnte, ist:

create index  idx_nc_note_parent(  
        parentId ,   
        parenttype  
    )  
    include (createdby, createdDate)  

Dies wäre nützlich, um kleine Listen der Notizen zu erstellen, in denen wir angeben können, wer und wann Informationen eingeben sollen.

Ich zögere, ein varchar(max)Feld aufzunehmen. Es scheint, als würde dies die Menge des zwischengespeicherten Index wirklich beeinträchtigen (ist dies vernünftig oder unangemessen)?

Angenommen, ich füge das NOTEFeld nicht hinzu, ist eine RID-Suche erforderlich, um den Notizinhalt tatsächlich abzurufen, wenn er angefordert wird.

Obwohl ich ziemlich viel darüber gelesen habe, wie teuer RID-Lookups sind, muss es immer noch besser sein, diesen Index zu haben, als einen Tabellenscan durchzuführen, RICHTIG?

[Entschuldigung für den Codeblock, ich habe die 4 Leerzeichen hinzugefügt, aber vielleicht habe ich es falsch gemacht? ]]

greg
quelle
Wie viele verschiedene Elterntypen haben Sie? Wenn sie nicht in Milliardenhöhe liegen, könnte diese Spalte viel enger gestaltet werden.
Ypercubeᵀᴹ
parentType könnte leicht auf 10 Zeichen verkleinert werden, aber ich glaube nicht, dass dies die Frage wesentlich beeinflusst. Was sind deine Gedanken?
Greg
Wie viele Zeilen erwarten Sie für eine durchschnittliche (parentId, parentType)Kombination zurück?
Jon Seigel
Es ist normalerweise eine kleine Anzahl. <10. Ein gutes Beispiel für diese Tabelle sind die Kommentare, die wir jetzt verwenden.
Greg
1
Ich denke, Sie meinen die Schlüsselsuche, nicht die RID-Suche. RID-Suchvorgänge werden auf Heaps ausgeführt, gerade weil es keinen Clustered-Index gibt (und keinen gültigen Index, der die Abfrage erfüllt).
Aaron Bertrand

Antworten:

5

Da Sie sagten, dass die meisten Abfragen im Allgemeinen nur wenige Zeilen zurückgeben würden, ist es für das Abrufen eines potenziell großen Felds vollkommen in Ordnung, die Abfrage eine RID-Suche verwenden zu lassen (in diesem Fall die Schlüsselsuche, da die Tabelle einen Clustered-Index hat). Für ein hochverfügbares System kann ich ohnehin nicht empfehlen, einen LOB-Typ in einen Index aufzunehmen, da dies Online-Neuerstellungen verhindert (für Versionen von SQL Server vor 2012). Außerdem müssen Sie sehr vorsichtig sein, dass der Abfrageplan immer an einem Suchplan festhält und nicht in einen Tabellenscan eintaucht, der sehr teuer sein kann. Dies ist ein Fall, in dem ich möglicherweise einen Tabellenhinweis (oder eine Plananleitung, wenn die Abfrage nicht geändert werden kann) verwende, auch wenn dies nicht unbedingt erforderlich ist.

Eine andere Möglichkeit besteht darin, den Clustered-Index für die Kombination von parentIdund neu zu erstellen, parentTypewenn diese Wertekombination statisch ist und im Allgemeinen mit der Zeit zunimmt. Es wäre jedoch besser, wenn parentTypees sich um einen integralen Typ handeln würde, und Sie sollten dies ohnehin ändern, um Speicherplatz zu sparen, wenn die Basistabelle groß ist oder wird. In Anbetracht dieser Änderung muss auch untersucht werden, wie sich dies auf die Indizierung für die anderen Klassen von Abfragen auswirken kann, die für diese Tabelle ausgeführt werden.

Wenn eine dieser beiden Methoden für die Arbeitslast nicht schnell genug ist, sollten Sie eine Daten-Caching-Lösung mit AppFabric implementieren, die sich viel einfacher skalieren lässt, als jedes Mal, wenn Sie Daten benötigen, eine SQL-Abfrage auszuführen. Dies kann eine enorme Auszahlung sein; Die Kosten sind zusätzliche Komplexität.

Jon Seigel
quelle
Ab SQL-Server 2012 wird die ONLINE-Neuerstellung jetzt für VARCHAR (MAX), NVARCHAR (MAX), VARBINARY (MAX) und XML unterstützt.
Calgary Coder
Danke für den Vorschlag. ParentId, ParentType, SEQ ist statisch, nimmt jedoch nie zu.
Greg
1

Kannst du das ausprobieren?

Erstellen Sie einen Index für parentID und parentType, um die entsprechenden IDs nachzuschlagen ...

Create  NonClustered Index idx_nc_note_parent On tblNote (parentID, parentType)

Verbinden Sie die IDs wieder mit der Basistabelle, um die gewünschten Informationen mithilfe des Clustered-Index abzurufen ...

Select  NOTE, createdDate, createdBy
From   (Select  ID
        From    tblNote
        Where   parentID = 12
        And     parentType = 'RFQ') n
Join    tblNote tn
        On  n.ID = tn.ID
Eric J. Price
quelle
Ich werde das versuchen und sehen, was der Abfrageplan tut. Je mehr ich darüber nachdenke, desto mehr denke ich, dass ich den Clustered Index möglicherweise in ParentId, ParentType, NoteId ändern sollte. (Das Hinzufügen von NoteId garantiert die Einzigartigkeit)
Greg
@greg Das wäre eine wirklich schlechte Idee. Wenn Sie eine Identitätsspalte haben, kann ich mir kein Szenario vorstellen, in dem Sie sie nicht als Clustered-Index verwenden möchten. Wenn Sie parentID verwenden, öffnen Sie sich für alle möglichen schrecklichen Fragmentierungsprobleme, es sei denn, Sie fügen nacheinander parentIDs ein. Wenn es sich um statische, unveränderliche Daten handelt, ist dies vermutlich auch in Ordnung. Wenn Sie dies tun und regelmäßig in die Tabelle einfügen, sollten Sie einen Füllfaktor von weniger als 100 verwenden, um Platz für neue Einsätze zu lassen.
Eric J. Price
1
Diese Antwort deutet darauf hin, dass die Verwendung eines Joins schneller sein wird als die Suche nach Schlüsseln / Lesezeichen. "Ja wirklich?"
Jon Seigel
@ Love2Learn - Ich denke du hast recht. Unterschiedliche übergeordnete Tabellen haben unterschiedliche Zeilenzahlen, sodass die übergeordnete ID nicht immer zunimmt. Es würde Wartung erfordern, da eine Fragmentierung einsetzen würde. Vielen Dank, dass Sie mir dabei geholfen haben, dies zu überdenken. Auf Ihren ursprünglichen Vorschlag, einen Join zu verwenden, war dies eine interessante Idee, und ich habe mir einige Gedanken darüber gemacht. Die Schlussfolgerung, zu der ich gekommen bin, ist, dass dies nicht schaden kann, aber es würde wahrscheinlich nicht helfen. Die Blattebenen des NC-Index enthalten bereits einen Schlüssel für den Clustered-Index. Das ist im Wesentlichen das, was der RID-Lookup ist, wenn ich Dinge verstehe.
Greg
Vielen Dank für alle Beiträge. Ich hatte gehofft, einen Test einzurichten und über das Wochenende durchzuführen, konnte aber die Zeit nicht zur Verfügung stellen.
Greg