2017-12-14 8 views
1

Dies ist für Firebird 2.5.Firebird SQL-Index für mehrere Spalten

Ich habe eine Tabelle T mit einem Index aus 2 Spalten, sagen ColA und ColB. Wenn ich tue: SELECT * FROM T WHERE ColA=..., so dass die WHERE-Klausel nur für Spalte A ist, wird Firebird einen Standardwert für die Spalte ColB setzen und den Index refinanzieren, oder kann er überhaupt diesen Index nicht verwenden?

Ein bisschen Kontext: Ich mache ein DB-Upgrade. Hier ist was ich habe:

CREATE TABLE user(
    newid BIGINT NOT NULL, 
    oldid BIGINT NOT NULL, 
    anotherCol INT); 

CREATE INDEX idx ON user(oldid, anotherCol); 

CREATE TABLE order(
    RefUser BIGINT); 

order.RefUser waren oldid und ich muss sie zu neuid ändern. Ich benutze es diese Abfrage:

UPDATE order o SET o.refuser = (SELECT u.newid FROM user u WHERE u.oldId = o.refuser); 

Zu diesem Zeitpunkt oldid ist immer noch einzigartig, aber später auf der Einzigkeit nur für (oldid, anotherCol) guaranted werden, daher den Index und die Schaffung von newid .

Benutzer Tabelle ist ein paar Millionen von Datensätzen, Auftragstabelle ist ein paar Dutzend Millionen: Diese Abfrage dauert mehr als eine Stunde. Ich würde gerne sehen, wie man es verbessern kann (nicht daran interessiert, einen kritischen Dienst für diese Zeitspanne abzuschalten).

+1

Wenn für die Spalten A und B ein Index in dieser Reihenfolge vorhanden ist, verwendet der FB diesen Index, wenn WHERE Bedingungen mit A oder mit A und B gleichzeitig enthält. Der Index wird jedoch nicht verwendet, wenn nur die B-Spalte in der WHERE-Klausel vorhanden ist . –

+0

@Andrej: ja Index ist auf A, B, und nur A ist in meiner WHERE-Klausel .. Also von dem, was Sie sagen Firebird wird den Index verwenden ... Also keine Optimierung von dieser Seite ... Vielen Dank für Diese präzise Antwort! – SoyonsPrecis

+0

@SoyonsPrecis Sie könnten einfach einen Test machen: PREPARE Ihre Abfrage und lesen Sie ihre Ausführung PLAN - gewährt, ob dieser Index verwendet werden würde oder nicht würde von Firebird nach dem bestimmten Datum in der Tabelle entschieden werden (aka Index SELECTIVITY). Aber allgemeine Regel ist, dass zusammengesetzte Indizes möglicherweise für jede Teilmenge der ersten Spalten verwendet werden, A oder A & B oder A & B & C usw. –

Antwort

3

Unter der Annahme, dass die Indexstatistik aktuell oder zumindest gut genug für den Optimierer ist, kann Firebird (und wird es oft) einen mehrspaltigen Index verwenden, wenn nicht alle Spalten Teil der where-Klausel sind . Die einzige Einschränkung ist, dass sie nur für die ersten Spalten (oder das 'Präfix' des Indexes) verwendet werden kann.

So mit

CREATE INDEX idx ON user(oldid, anotherCol); 

Firebird den Index idx gut für where oldid = 'something' verwenden können, aber nicht für where anotherCol = 'something'.

Und nein, Firebird nicht "legen Sie einen Standardwert für die Spalte [anotherCol]". Es führt einen Bereichsscan für den Index durch und gibt alle Zeilen mit dem übereinstimmenden Präfix oldid zurück.

Technisch Firebird erstellt Indexschlüssel durch die Spalten kombiniert, wie in Firebird for the Database Expert: Episode 1 - Indexes beschrieben, die den Wert in dem Index bedeutet, ist so etwas wie:

0<oldid> 1<anotherCol> : row_id 

zB (vereinfacht, wie im wirklichen Leben Firebird hat auch ein Präfix Kompression)

0val1 1other1 : rowid1 
0val1 1other2 : rowid4 
0val1 1other3 : rowid6 
0val2 1other1 : rowid2 
... 

wenn where oldid = 'val1' verwenden, Firebird den Index für alle Einträge, die mit 0val1 1 beginnen suchen (als ob es eine Zeichenfolge Suche nach 0val1 1% auf einem einzigen tun Säule). Und in diesem Fall wird es rowid1, rowid4 und rowid6 übereinstimmen.

Obwohl dies funktioniert, wenn Sie viel nur auf oldid abfragen, könnte es auch besser sein, einen einzigen Spaltenindex nur auf oldid zu erstellen, da dieser Index kleiner und daher schneller bei der Suche nach Datensätzen ist. Der Nachteil besteht natürlich darin, dass mehr Indizes Auswirkungen auf die Einfügungen, Aktualisierungen und Löschungen haben.

Siehe auch Concatenated Indexes unter Use The Index, Luke.

+0

'die Indexstatistiken sind auf dem neuesten Stand oder zumindest gut genug für den Optimierer' nur der zweite Teil entscheidet, ob der Server es benutzen würde :-) Während es wichtig ist, Statistiken auf dem neuesten Stand zu halten, wird die Entscheidung getroffen, die Indexselektivität zu vergleichen wie sie bekannt sind. Wenn Daten irgendwie veraltet sind - Optimizer würde es immer noch benutzen, denn wenn es wüsste - es würde es nur aktualisieren :-D –