SQL Server - Index für eine berechnete Spalte?
-
19-09-2019 - |
Frage
Ich bin bei zu einem Tisch Dutzende von verschiedenen Zeiten, und jedes Mal, ich join (oder Filter), basierend auf den Ergebnissen eine SUBSTRING von einem der Säulen (es ist eine Zeichenfolge, aber links aufgefüllt mit Nullen, und ich kümmere mich nicht um die letzten vier Ziffern). Als Ergebnis, obwohl diese Spalte indiziert ist und meine Abfrage würde den Index verwendet, hat es einen Table-Scan, weil das SUBSTRING selbst ist nicht indiziert, so SQL Server hat es für jede Zeile zu berechnen, bevor wie es Beitritt.
Ich suche nach irgendwelchen Ideen, wie man diesen Prozess zu beschleunigen. Derzeit gibt es einen Blick auf dem Tisch (es ist ein „SELECT * FROM“, sondern nur der Tabelle, einen Namen zu geben), und ich überlege, eine Spalte zu der Ansicht hinzufügen, die berechnet ist, und dann, dass die Indizierung. Ich bin offen für andere Vorschläge, obwohl - irgendwelche Gedanken
Weitere Einzelheiten: Ich sollte dies beginnen geteilt haben. Die Tabelle erhält die Replikation von unserem Abrechnungssystem, so der Bearbeitung der zugrunde liegende Tabelle eine berechnete Spalte ist keine Option hinzuzufügen. Jede berechnete Spalte müßte die Ansicht auf dem Tisch hinzugefügt werden. Auch sind die führenden Nullen nicht immer führende Nullen -. Sie manchmal andere Daten sind, dass ich nicht daran interessiert, ich die eigentliche Frage annimmt „ist Wie kann ich Daten in der Mitte eines VARCHAR-Spalte verbinden, während auch die Verwendung eines Index zu machen? Volltextsuche? "
Klärende meines Beispiel Ich bin eine Vereinfachung, aber im Wesentlichen, sagen wir, ich versuche Werte mit den folgenden Werten in einer Spalte zu sehen:
00000012345MoreStuff
00000012345Whatever
19834212345
Houses12345837443GGD
00000023456MoreStuff
Ich bin in Reihen interessiert, wo SUBSTRING (7,5) = „12345“, so dass ich Zeilen 1-4 wollen würde, aber die Zeile nicht 5. Was ich vorschlage, eine Spalte zu meiner „SELECT ist das Hinzufügen * "Ansicht, dass diese Teilkette in sich hat, und dann auf die Indizierung basiert. Heißt das mehr Sinn machen?
Lösung
Angenommen, Sie haben Ihre Felder in diesem Format:
00Data0007
000000Data0011
0000Data0015
, können Sie die folgenden Schritte ausführen:
-
Erstellen Sie eine berechnete Spalte:
ndata AS RIGHT(REVERSE(data), LEN(data) - 4)
Dies wird Ihre Spalten in die folgenden Transformation:
ataD00 ataD000000 ataD0000
-
Erstellen Sie einen Index für diese Spalte
-
Geben Sie diese Abfrage für die Zeichenfolge
Data
suchen:SELECT * FROM mytable WHERE ndata LIKE N'ataD%' AND SUBSTRING(ndata, LEN(N'ataD') + 1, LEN(ndata)) = REPLICATE('0', LEN(ndata) - LEN('ataD'))
Die erste Bedingung wird, einen Index für die Grobfilterung verwenden.
Die zweite wird sicherstellen, dass alle führenden Zeichen (welche die nachfolgenden Zeichen in der berechneten Spalte wurde) sind nichts anderes als Nullen.
Sehen Sie diesen Eintrag in meinem Blog für die Leistung Detail:
Aktualisieren
Wenn Sie nur einen Index für SUBSTRING
wollen, ohne Ihr Schema zu ändern, das Erstellen einer Ansicht eine Option ist.
CREATE VIEW v_substring75
WITH SCHEMABINDING
AS
SELECT s.id, s.data, SUBSTRING(data, 7, 5) AS substring75
FROM mytable
CREATE UNIQUE CLUSTERED INDEX UX_substring75_substring_id ON (substring75, id)
SELECT id, data
FROM v_substring75
WHERE substring75 = '12345'
Andere Tipps
Fügen Sie ein berechnete Spalte auf den Tisch und erstellen einen Index für diese Spalte.
ALTER TABLE MyTable
Add Column CodeHead As LEFT(Code,Len(Code)-4)
Dann einen Index für diese erstellen.
CREATE INDEX CodeHeadIdx ON MyTable.CodeHead
Können Sie erneut Ausdruck Ihren Filterkriterien in Bezug auf eine LIKE ‚etwas%‘ Aussage? (Dies gilt für einen Index)
Ändern Sie die Spalte auf zwei Säulen - die Daten, die Sie kommen auf und die zusätzlichen 4 Zeichen. Unter Verwendung von Teilen einer Spalte verlangsamt Dinge nach unten, wie Sie gesehen hve