2016-06-20 5 views
4

Auf this question, die ich neulich fragte ich bekam den folgenden Kommentar.Warum verhindern Funktionen auf Spalten die Verwendung von Indizes?

In fast jeder Datenbank verhindert fast jede Funktion in einer Spalte die Verwendung von Indizes. Es gibt Ausnahmen hier und da, aber im allgemeinen Funktionen verhindern, dass die Verwendung von Indizes

Ich googeln um und fand mehr erwähnt dieses gleiche Verhalten, aber ich hatte Mühe, etwas mehr in die Tiefe zu finden, als das, was der Kommentar bereits gesagt mich.

Könnte jemand näher erläutern, warum dies geschieht, und vielleicht Strategien, um das zu vermeiden?

+0

Es gibt zumindest in Oracle Funktionsindizes. Das ist vielleicht eine der Ausnahmen hier und da :-) –

Antwort

2

Ein Index in seiner grundlegendsten Form ist nur die sortierte Spalte Daten, so dass es leicht, um einen Wert zu suchen. Zum Beispiel kann ein Lehrbuch die Seiten in einer bestimmten Reihenfolge haben, aber dann einen Index auf der Rückseite für alle Begriffe haben. Wie Sie sehen, werden die Daten vorberechnet/sortiert und in einem separaten Bereich gespeichert.

Wenn Sie eine Funktion auf die Spalte anwenden und versuchen, basierend auf der Ausgabe zu suchen/zu filtern, ist der Index nicht länger nützlich. Lassen Sie uns noch einmal unser Buchbeispiel betrachten und sagen, dass die Funktion, die wir anwenden, die Umkehrung des Ausdrucks ist (so wird reverse('integral') zu 'largetni'). Sie werden diesen Wert nicht im Index finden, also müssen Sie alle Begriffe nehmen, sie durch die Funktion setzen und erst dann vergleichen. Alles zur Abfragezeit. Ursprünglich konnten wir die Suche nach i, dann in, dann int und so weiter überspringen, so dass es einfach ist, den Begriff zu finden, so dass die Funktion alles viel langsamer machte.

Wenn Sie häufig mit dieser Funktion abfragen, können Sie einen Index mit reverse(term) vorzeitig erstellen, um die Suche zu beschleunigen. Aber ohne es explizit zu tun, wird es immer langsam sein.

2

Die Indizes werden getrennt von den Daten selbst auf dem SQL Server gespeichert. Wenn Sie also eine Abfrage ausführen, kann der B-Tree-Index, auf den verwiesen werden sollte, um die Geschwindigkeit anzugeben, nicht mehr referenziert werden, da eine Operation (die Funktion) für jede Spalte vorhanden ist. Daher wird der Abfrageoptimierer den Index nicht verwenden nicht mehr.

2

Hier ist eine gute Erklärung, warum dies der Fall ist (dies ist ein SQL-Server bestimmte Artikel, aber trifft wahrscheinlich auch auf andere SQL-RDBMS-Systeme):

https://www.mssqltips.com/sqlservertip/1236/avoid-sql-server-functions-in-the-where-clause-for-performance/

Die Linie von dem Artikel, der wirklich heraus steht ist "Der Grund dafür ist, dass der Funktionswert für jede Zeile von Daten ausgewertet werden muss, um festzustellen, ob sie mit Ihren Kriterien übereinstimmt."

2

Betrachten wir ein extremes Beispiel. Nehmen wir an, Sie suchen eine Zeile mit einer kryptografischen Hash-Funktion wie HASH(email_address) = 0x123456. Die Datenbank hat einen Index, der auf email_address aufgebaut ist, aber jetzt werden Sie gebeten, Daten auf HASH(email_address) nachschlagen, die es nicht hat. Es könnte immer noch den Index verwenden, aber es würde am Ende jeden einzelnen Indexeintrag für email_address suchen und sehen, ob HASH(email_address) übereinstimmt. Wenn der gesamte Index gescannt werden muss, kann stattdessen auch nur die gesamte Tabelle gescannt werden, sodass nicht einzelne Zeilenpositionen abgerufen werden müssen.

Verwandte Themen