Frage

Angenommen, ich eine Datenbanktabelle mit zwei Feldern haben, „foo“ und „bar“. Keiner von ihnen sind einzigartig, aber jeder von ihnen ist indiziert. Anstatt jedoch zusammen indiziert, sie jeweils einen separaten Index haben.

Jetzt nehme ich eine Abfrage wie SELECT * FROM sometable WHERE foo='hello' AND bar='world'; Meine Tabelle, die eine große Anzahl von Zeilen auszuführen, für die foo ‚Hallo‘ und eine kleine Anzahl von Zeilen, für die Bar ‚Welt‘.

So ist die effizienteste Sache für den Datenbankserver unter der Haube zu tun ist, um den Bar-Index verwenden, um alle Felder zu finden, wo Bar ‚Welt‘ ist, dann wieder nur die Zeilen, für die foo ‚Hallo‘. Dies ist O(n) wobei n die Anzahl der Zeilen ist, wo bar ist ‚Welt‘.

Doch ich denke, es ist möglich, dass der Prozess in umgekehrter Richtung passieren würde, wo der fo Index verwendet und durchsuchten die Ergebnisse. Dies würde O(m) wobei m die Anzahl der Zeilen ist, wo foo ‚Hallo‘.

So ist Oracle intelligent genug, um effizient hier zu suchen? Was ist mit anderen Datenbanken? Oder gibt es eine Art, wie ich es in meiner Frage sagen kann, in der richtigen Reihenfolge zu suchen? Vielleicht durch bar='world' zuerst in der WHERE Klausel setzen?

War es hilfreich?

Lösung

Oracle wird mit ziemlicher Sicherheit verwenden, um den selektivsten Index die Abfrage zu fahren, und Sie können überprüfen, dass mit dem Plan erklären.

Darüber hinaus kann Oracle die Verwendung beider Indizes in ein paar Möglichkeiten kombinieren - es kann btree Indizes in Bitmaps umwandeln und eine Bitmap und den Betrieb auf sie durchführen, oder es kann ein Hash-Join auf der Rowid der durch die beiden zurückführen Indizes.

Eine wichtige Überlegung hier möglicherweise eine Korrelation zwischen den Werten abgefragt werden. Wenn foo = ‚Hallo‘ für 80% der Werte Konten in der Tabelle und bar = ‚Welt‘ Konten für 10%, dann wird Oracle gehen davon aus, dass die Abfrage 0,8 * 0,1 = 8% der Tabellenzeilen angezeigt werden kann. Allerdings kann dies nicht richtig sein - die Abfrage tatsächlich 10% der rwos oder sogar 0% der Zeilen zurückgeben kann, je nachdem wie korrelierten die Werte sind. Nun, je nach Verteilung dieser Zeilen in der gesamten Tabelle kann es nicht effizient sein, einen Index zu verwenden, um sie zu finden. Unter Umständen müssen Sie noch den Zugriff auf (sagen wir) 70% oder die Tabellenblöcke die erforderlichen Zeilen (google für „Clustering-Faktor“) abgerufen werden, wobei in diesem Fall Oracle eine ful Tabelle ausführen wird scannen, wenn es um die Schätzung korrekt wird.

In 11g können Sie mehrspaltige Statistiken sammeln mit dieser Situation zu helfen, glaube ich. In 9i und 10g können Sie Dynamisierung verwenden, um eine sehr gute Schätzung der Anzahl der Zeilen abgerufen werden zu bekommen.

Um den Ausführungsplan tut diese:

explain plan for
SELECT *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

Kontrast, mit:

explain plan for
SELECT /*+ dynamic_sampling(4) */
       *
FROM   sometable
WHERE  foo='hello' AND bar='world'
/
select * from table(dbms_xplan.display)
/

Andere Tipps

Ja, können Sie „Hinweise“ mit der Abfrage zu Oracle geben. Diese Hinweise werden als Kommentare ( „/ * HINWEIS * /“) in die Datenbank verkleidet und sind vor allem herstellerspezifisch. So ein Hinweis für eine Datenbank nicht auf einer anderen Datenbank arbeiten.

würde ich Index Hinweise hier verwenden, den ersten Hinweis für den kleinen Tisch. Siehe hier .

Auf der anderen Seite, wenn Sie oft über diese beiden Felder suchen, warum nicht einen Index für diese beide erstellen? Ich habe nicht die richtige Syntax, aber es wäre so etwas wie

CREATE INDEX IX_BAR_AND_FOO on sometable(bar,foo);

Auf diese Weise Datenabruf soll ziemlich schnell sein. Und für den Fall der Verkettung ist einzigartig hten Sie einfach einen eindeutigen Index erstellen, die blitzschnell sein sollte.

Eli,

In einem Kommentar, den Sie schrieb:

  

Leider habe ich eine Tabelle mit vielen Spalten mit jeweils ihren eigenen Index. Benutzer können eine beliebige Kombination von Feldern abgefragt werden, so kann ich nicht effizient Indizes auf jedem Feld Kombination erstellen. Aber wenn ich nur zwei Felder benötigen Indizes hatte, würde ich vollständig mit Ihrem Vorschlag zustimmen zwei Indizes zu verwenden. - Eli Courtwright (29. September um 15:51 Uhr)

Das ist eigentlich ziemlich wichtige Informationen. Manchmal austricksen Programmierer selbst wenn Fragen zu stellen. Sie versuchen, die Frage bis zu den zukunftsträchtigen Punkten zu destillieren, aber ziemlich oft über vereinfachen und verpassen die beste Antwort zu bekommen.

In diesem Szenario wird gerade deshalb Bitmap-Indizes erfunden wurden - die Zeiten, zu handhaben, wenn unbekannte Gruppen von Spalten in einer Klausel verwendet werden würden, wo.

Für den Fall, jemand sagt, dass BMIs nur für geringe Mächtigkeit Spalten sind und auf Ihren Fall nicht zutrifft. Low ist wahrscheinlich nicht so klein, wie Sie denken. Das einzige wirkliche Problem ist die Parallelität von DML auf den Tisch. Muss Single-Threaded oder selten sein, damit dies funktioniert.

  

So ist Oracle intelligent genug, um suchen   effizient hier?

Die einfache Antwort ist „wahrscheinlich“. Es gibt lots'o‘sehr hell Menschen an jedem der Datenbankhersteller arbeiten an den Abfrageoptimierer optimiert, so ist es wahrscheinlich, Dinge zu tun, die Sie nicht einmal gedacht. Und wenn man die Statistiken aktualisieren, es wird wahrscheinlich noch mehr.

Als erstes werde ich davon ausgehen, dass Sie schön reden, normal, Standard b * -Baum-Indizes. Die Antwort für Bitmap-Indizes ist radikal anders. Und es gibt viele Optionen für verschiedene Arten von Indizes in Oracle, die möglicherweise nicht die Antwort ändern.

Zumindest wenn das Optimierungsprogramm der Lage ist, um die Selektivität eines bestimmten Zustands, um zu bestimmen, wird es den selektiveren Index (das heißt der Index auf bar) zu verwenden. Aber wenn man schief Daten (es gibt N Werte in der Spalte Bar, aber die Selektivität für einen bestimmten Wert ist wesentlich mehr oder weniger als 1 / N der Daten), würden Sie ein Histogramm auf der Säule zu haben, um brauchen, um zu sagen, das Optimierungsprogramm die Werte mehr oder weniger wahrscheinlich sind. Und wenn Sie Bind-Variablen verwenden (wie alle guten OLTP-Entwickler sollten), abhängig von der Oracle-Version, können Sie Probleme mit Bind Variable spähen haben.

Potenziell, Oracle könnte sogar eine on the fly Umwandlung der beiden b * -Baum-Indizes in Bitmaps tun und die Bitmaps kombinieren, um beide Indizes zu verwenden, um die Zeilen zu finden, es muss abgerufen werden. Aber das ist ein eher ungewöhnlicher Abfrage-Plan, vor allem, wenn es nur zwei Spalten, in denen eine Spalte hoch selektiv ist.

Ich bin sicher, Sie können auch haben Oracle einen Abfrageplan angezeigt werden, so dass Sie genau sehen können, welcher Index zum ersten Mal verwendet wird.

können Sie geben Hinweise auf die Index zu verwenden. Ich bin nicht vertraut mit Oracle, aber in Mysql können Sie USE verwenden | IGNORE | FORCE_INDEX (siehe hier für weitere Details). Für die beste Leistung allerdings sollten Sie einen kombinierten Index verwenden.

Der beste Ansatz wäre foo bar Index hinzuzufügen, oder fügen Sie bar foo-Index (oder beides). Wenn foo Index auch einen Index für Leiste enthält, dass zusätzliche Indizierungsebene nicht die Nützlichkeit des foo Index in alle aktuellen Anwendungen dieses Index beeinflussen, noch wird es merklich die Leistung der Aufrechterhaltung dieser Index beeinflussen, aber es wird die Datenbank zusätzlich geben Informationen für die Arbeit mit in Anfragen wie im Beispiel zu optimieren.

Es ist besser als das.

Index Sucht ist immer schneller als Full-Table-Scans. So hinter den Kulissen Oracle (und SQL Server für diese Angelegenheit) zunächst den Bereich der Zeilen auf beiden Indizes finden. Es wird dann schauen, welcher Bereich kürzer ist (zu sehen, dass es eine innere Verknüpfung), und es wird die kürzere Reichweite zu finden, die Spiele mit dem größeren der beiden.

iterieren
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top