![]() |
Datenbank: Firebird • Version: 2.5 • Zugriff über: FibPlus
Ausführunsplan / SQL Optimizer
Hallo zusammen,
ich habe da ein Problem mit einer harmlosen Query: select v2ps.par, v2ps.v2fertigartikel, v2fertigartikel.artikelbezeichnung from v2ps inner join v2fertigartikel on (v2ps.v2fertigartikel=v2fertigartikel.id) where v2ps.status in ('U','A') Ein ganz simpler Fall. Betriebsaufträge bestimmter Stati werden mit Artikelstammdaten verknüpft. Selbstverständlich funktioniert diese Abfrage und liefert das korrekte Ergebnis. Aber wenn ich mir den Ausführungsplan in IBExpert ansehe steht da: Plan: PLAN JOIN (V2FERTIGARTIKEL NATURAL, V2PS INDEX (V2PS_IDX3)) NATURAL??? In der Tabelle V2FERTIGARTIKEL ist das Feld ID vom Typ integer und der Primärschlüssel. Der dazugehörige Index heisst RDB$PRIMARY46. Warum wird dieser Index nicht benutzt? Bei größeren Datenmengen könnte das zum ernsten Problem werden. Ober habe ich da ganz grundsätzlich missverstanden oder übersehen? Vielen Dank, Martin |
AW: Ausführunsplan / SQL Optimizer
Ist v2ps.v2fertigartikel ebenfalls integer? Liegt dort ebenfalls ein index drüber?
Oder versuch doch mal so:
Code:
select
v2ps.par, v2ps.v2fertigartikel, v2fertigartikel.artikelbezeichnung from v2ps,v2fertigartikel where v2ps.status in ('U','A') and v2ps.v2fertigartikel=v2fertigartikel.id |
AW: Ausführunsplan / SQL Optimizer
@gmc616: Danke für deine Antwort. Natürlich ist das Feld vom Typ integer. Leider nicht als FK definiert obwohl es an dieser Stelle Sinn machen würde. Aber das sollte keinen Einfluss auf den Optimizer haben.
Deine Abfrage führt zum gleichen Plan. Es ist also egal ob mit JOIN oder WHERE die Tabellen verbinde. Es bleibt bei NATURAL. Ich bin echt ratlos. |
AW: Ausführunsplan / SQL Optimizer
Sorry, ich bin in FB nicht fit, nutze ihn garnicht.
Die Überlegung war, dass evtl. die beiden IDs unterschiedliche Integer (smallint, longint etc.) sein könnten und deswegen FB einen eigenen Index zusammen baut. Die Erfahrung zeigt auch, das manchmal ein einfaches umbauen des Statements die SQL-Engine dazu veranlasst, anders zu arbeiten ( z.B. die andere Tabelle indiziert ). z.B. einfach mal umdrehen
Code:
oder das FROM umstellen ...
v2fertigartikel.id=v2ps.v2fertigartikel
oder evtl. einen FK zusätzlich über v2fertigartikel.id ist aber alles nur geraten, wie erwähnt, kenne/nutze ich FB nicht. |
AW: Ausführunsplan / SQL Optimizer
Die Felder sind beide als INTEGER NOT NULL deklariert. Ein Umdrehen des Vergleiches habe ich auch schon versucht. Das bringt nichts. Ich wäre aber auch schreiend aus dem Fenster gesprungen wenn das funktioniert hätte....
Ich werde jetzt mal das mit dem FK probieren. Allerdings laufen ein paar ältere Anwendungen auf der Datenbank. Da bin ich mir nicht sicher welche Seiteneffekte ich mir mit der Deklarion des FK einhandle. Ich sehe die Exceptions durch constraints violations schon vor meinem geistigen Auge. Schaun mer mal. Trotzdem Danke, Martin |
AW: Ausführunsplan / SQL Optimizer
Kann es sein, dass auf v2ps.status auch ein Index ist, und er diesen im ersten Schritt (bevor er den eigentlichen Join durchführt) verwendet, um die Zeilen von v2ps anhand der where-Bedingung einzugrenzen? Dann kommen anschließend die ids unsortiert heraus, sodass er keinen Merge-Join durchführen kann (und daher von den Indizes auf den id-Spalten nicht profitiert).
Vorausgesetzt, ich habe diesen Query Plan überhaupt richtig interpretiert... habe auf die Schnelle irgendwie keine Dokumentation dazu gefunden, wie diese Ausgabe überhaupt zu lesen ist. Ich würde auf jeden Fall mal die Where-Bedingung testweise weglassen, um zu gucken, was passiert. |
AW: Ausführunsplan / SQL Optimizer
Vielleicht ist die Tabelle 'v2FertigArtikel' zu klein?
|
AW: Ausführunsplan / SQL Optimizer
Zu klein ist so eine Sache. Im Augenblick sind knapp 8.000 Datensätze drin.
Die Performance der Abfrage ist im Augenblick auch kein Problem. Der Firebird läuft auf einer Mödermaschine unter Ubuntu Server. Granatenschnell. Aber die Datenmenge wird bald steil nach oben gehen. Ich rechne mit mehr als 1.500 neuen Einträgen/Monat ab Ende des Jahres. Und es geht auch um das Grundsätzliche. Ich sehe da ein Problem. |
AW: Ausführunsplan / SQL Optimizer
@Namenloser: Ja. Auf Feld STATUS gibt es einen Index. Warum das aber dazu führen sollte dass der Index für den PK in v2fertigartikel nicht benutzt wird ist mir nicht klar.
Es ist eine simple 1-1 Beziehung. Aber trotzdem Danke. |
AW: Ausführunsplan / SQL Optimizer
Vielleicht ist
![]() Gruß K-H P.S. Das Umstellen der Tabellenreihenfolge im FROM kenn ich noch von den älteren MSSQL-Servern, da waren Abfragen noch handoptimiert. |
AW: Ausführunsplan / SQL Optimizer
Neben dem Ausführungsplan wären auch noch IO Statistiken in Form von Indexed vs. Non-Indexed Reads auf den Tabellen interessant.
Regel Nummer 1 beim Performance testen ist das Ganze mit einer repräsentativen Datenmenge zu machen. Füll dir die Tabellen mal mit einem Datengenerator an und dann schau mal, ob sich hier was ändert. Thomas |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Folgende Tabellen als Beispiel:
Code:
Beide Tabellen haben einen Index auf Spalte A (aufsteigend sortiert), und die Abfrage ist Tabelle X Tabelle Y A B A C --------- --------- 1 42 2 0 2 27 3 1 3 40 4 2 5 38 5 3 7 39 7 4 9 41 9 5
Delphi-Quellcode:
.
select A, B, C from X join Y on X.A = Y.A
Man geht nach folgendem Pseudocode vor:
Code:
(Zur Vereinfachung gehe ich hier mal davon aus, dass A in beiden Tabellen unique ist. Man kann den Algorithmus aber auch für nicht-unique Fälle verallgemeinern).
CursorX := Zeiger auf erste Zeile von Tabelle X.
CursorY := Zeiger auf erste Zeile von Tabelle Y. while (not CursorX.EOF and not CursorY.EOF) do begin if CursorX.A = CursorY.A then Elemente von CursorX und CursorY konkatenieren und Zeile ausgeben else if CursorX.A > CursorY.A then CursorY eine Zeile weiter nach unten bewegen else if CursorX.A < CursorY.A then CursorX eine Zeile weiter nach unten bewegen end; Das ist ein recht effizienter Join-Algorithmus, allerdings nur dann wirklich effizient, wenn die es für die Eingabemengen schon sortiert sind. Im obigen Beispiel ist das der Fall dank des Index. Wenn die Abfrage jetzt aber stattdessen wäre
Delphi-Quellcode:
und auf B ein Index liegt, dann kann es sein, dass der Optimizer sich entscheidet erst mal nach der Bedingung zu filtern und dabei den Index auf B zu nutzen.
select A, B, C from X join Y on X.A = Y.A where X.B in (42, 27, 38, 39)
Zwischenergebnis:
Code:
Da der Index auf B benutzt wurde, sind die Zeilen von X' nun möglicherweise in einer anderen Reihenfolge und nicht mehr nach A sortiert. Folglich kann der Join nun nicht mehr so effizient mit dem Merge-Join-Algorithmus durchgeführt werden. Man könnte jetzt natürlich X' einfach noch mal extra nach A sortieren, aber möglicherweise ist es effizienter, gleich einen ganz anderen Join-Algorithmus zu verwenden, z.B. Hash-Join. Dabei nützt einem dann allerdings auch der Index auf Tabelle Y nichts mehr, weshalb er nicht benutzt wird.Tabelle X' Tabelle Y A B A C --------- --------- 2 27 2 0 5 38 3 1 7 39 4 2 1 42 5 3 7 4 9 5 Ist aber nur geraten, ich hab keine Ahnung, was der Optimizer intern macht und was für Algorithmen er verwendet. |
AW: Ausführunsplan / SQL Optimizer
Dann brauch ich aber keinen B+ Baum. Ich habe das so umgesetzt:
Code:
Wobei CursorX meist auf die Tabelle zeigt, die kleiner ist bzw. bei der alle 'A'-Werte insgesamt schneller zu lesen sind (z.B. weil die Tabelle kleiner ist, oder ein Index vorliegt oder beides oder oder oder).
CursorX auf 1.Zeile
while not CursorX.EOF do if CursorY.FindFirst(CursorX.A) then repeat Output CursorX.joined(CursorY); until not CursorY.FindNext(CursorX.A); CursorX.GotoNext Der Optimizer wird diese Strategie verwenden, wenn er für das Suchen des korrespondierenden Eintrags eine schnelle B*-Suche verwenden kann (fast O(1)) und Indexe für beide Tabellen auf 'A' vorhanden sind und die Tabelle 'X' nicht all zu viele unterschiedliche 'A' besitzt. Im Extremfall ist die eine Tabelle nur 1 Zeile lang, dann habe ich den korrespondierenden Eintrag aus der anderen Tabelle in O(1) gefunden. Bei deiner Version ist das O(n). Es kann allerdings sein, das 'dein' Scan schneller ist. Z.B. wenn beide Tabellen in etwa gleich groß sind und es viele unterschiedliche 'A' in beiden Tabelle gibt. Es wird bestimmt Heuristiken geben, die ausrechnen, wann welche Schleife verwendet wird (der 'Optimizer'). Wozu sind denn sonst die Indexstatistiken gut? Dein Algorithmus bricht blöderweise ab, wenn ein Schlüssel 'A' in X größer ist als der größte in Y (wenn also CursorY.EOF = true) ist. Aber ich weiß, wie Du das meinst. Blöd ist der jedenfalls nicht, der Algo. |
AW: Ausführunsplan / SQL Optimizer
Hallo,
reduzier mal deine Query schrittweise select v2ps.par, v2ps.v2fertigartikel, v2fertigartikel.artikelbezeichnung from v2ps inner join v2fertigartikel on (v2ps.v2fertigartikel=v2fertigartikel.id) where v2ps.status in ('U','A') select v2ps.par, v2ps.v2fertigartikel, v2fertigartikel.artikelbezeichnung from v2ps inner join v2fertigartikel on (v2ps.v2fertigartikel=v2fertigartikel.id) // das fliegt erst mal raus where v2ps.status in ('U','A') Vielleicht mag er das IN nicht ? Das ginge ja auch über OR. Von welcher FB-2.5-Version reden wir eigentlich ? Heiko |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Aber du hast natürlich recht, dass die beste Strategie immer von den Daten selbst abhängt. Es kann daher eben z.B. auch schneller sein, einen stumpfen Table-Scan durchzuführen als den Index zu benutzen, weil konsekutives Lesen schneller ist als Random-Access. |
AW: Ausführunsplan / SQL Optimizer
(abbrechen) Autsch, ja. Stimmt.
|
AW: Ausführunsplan / SQL Optimizer
Zunächst mal vielen Dank für die vielen Antworten.
Zunächst @tsteinmaurer: Klar. Man sollte mit einer Datenmenge testen die dem worst-case nahekommt. Das werde ich auch tun. Aber zunächst mal folgendes: Die Statistik indexed vs. natural reads habe ich mir angesehen und verstehe nicht wirklich was da vor sich geht. Situation ist wie beschrieben folgende: v2ps -> Betriebsaufträge, 241.954 Datensätze v2ps.v2fertigartikel = integer not NULL, v2fertigartikel -> wie der Name sagt: Artikelstammdaten, 7.782 Datensätze v2fertigartikel.id = integer, natürlich NOT NULL da PK Die Abfrage wie gehabt: select v2ps.par, v2ps.v2fertigartikel, v2fertigartikel.artikelbezeichnung from v2ps inner join v2fertigartikel on (v2ps.v2fertigartikel=v2fertigartikel.id) where v2ps.status in ('U','A') Ausgabe des Plans (IBExpert) PLAN JOIN (V2FERTIGARTIKEL NATURAL, V2PS INDEX (V2PS_IDX3)) Statistik: NonIndexed Reads (v2fertigartikel): 7.782 !!!!! Indexed Reads (v2ps): 241.934 !!! Der vom Plan verwendete Index V2PS_IDX3 indexiert die Felder (V2FERTIGARTIKEL,V2FARBE), ist also völlig unbrauchbar im Kontext der Abfrage. Entweder spinnt die Ausgabe des IBExpert oder der Optimizer erzeugt seinen Plan nach sehr esoterischen Kriterien. @hoika Das Query reduziert habe ich. Ebenfalls das IN durch ein OR ersetzt. Es ändert genau garnichts. Ich bin echt verwundert. |
AW: Ausführunsplan / SQL Optimizer
Zum Pseudocode: Vielleicht bin ich da zu naiv, aber in den alten Zeiten in denen man noch selbst mit Indexen 'rumhantierte hätte meine Lösung wie folgt ausgesehen:
foreach status in menge seek status in v2psindex while v2psindex.staus = status; seek v2ps.v2fertigartikel in v2fertigartikelindex ergebnismenge.add ( v2ps.par, v2fertigartikel.artikelbezeichnung) next in V2PsIndex; end end Ergibt (Anzahl gesuchter Stati) Suchevorgänge im Index von v2ps, in meinem Fall genau zwei. Dann noch (Anzahl gefundener passender stati ) Suchvorgänge im Index v2fertigartikel. In meinem Besispiel wären das 864. Beide Tabellen verfügen über genau die Indexe die benötigt werden die Abfrage optimal auszuführen Grüße, Martin |
AW: Ausführunsplan / SQL Optimizer
Zitat:
|
AW: Ausführunsplan / SQL Optimizer
Zitat:
beleibt unklar. Die Indexierten Felder V2FERIGARTIKEL und V2FARBE sind kein Kriterium für die erwartete Ergebnismenge aus v2ps. Hier bilden die Sätze mit den gesuchten Stati das gewünschte Ergebnis. |
AW: Ausführunsplan / SQL Optimizer
Das Feld 'V2FERTIGARTIKEL' wird in der JOIN-Klausel verwendet, oder etwa nicht?? Die Farbe zwar nicht, aber der Index gibt trotzdem eine sortierte Liste der V2FERTIGARTIKEL, da V2FARBE *hinter* V2FERTIGARTIKEL im Index steht. Da kommen dann zwar einige Einträge doppelt vor, aber wenn der Optimizer sonst nichts hat, nimmt er eben diesen Index.
Code:
Vermutlich denkt er, das er damit schneller ans Ziel kommt, als einen anderen Index zu verwenden. Vielleicht ist FB so beschränkt und kann immer nur einen Index pro Verknüpfung verwenden. Keine Ahnung. Auf jeden Fall ist der Index sehr wohl ein Kandidat für eine Optimierung, da eben (zum 3.Mal) das Feld V2FERTIGARTIKEL in der ON-Klauses des JOINs vorkommt. Siehe dazu auch den Pseudocode vom Namenlosen und von mir. Die hätten zwar gerne zwei Indexe, aber einer reicht auch. Dann geht er die Tabelle v2FertigArtikel vielleicht schrittweise durch und sucht -hurtig wie er ist- in dem Index 'V2PS_IDX3' einen passenden Eintrag
select ...
from v2ps inner join v2fertigartikel on (v2ps.v2fertigartikel=v2fertigartikel.id) -- <<<<<<< Mööööööp where v2ps.status in ('U','A') Mal wieder Pseudocode:
Code:
Klingt nach einem (Query-)plan. Findest Du nicht?
Foreach record2 in table v2FertigArtikel do
if V2PS_IDX3.HasValueForField('V2FERTIGARTIKEL', record2.Id, out recordnumber) then record1 = v2p2.LoadRecord (recordnumber); output record1.JoinWith(record2) |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Man kann ja mal die Laufzeit verschiedener Verfahren mal über den Daumen abschätzen: Merge-Join (beide Indizes): 7 782 + 241 954 = 249 736 Nested Loop (nur Index über v2fertigartikel): 241 954 * log(7 782) = 941 465 Nested Loop (nur Index über v2ps): 7 782 * log(241 954) = 41 896 Was er da macht ist also schon das Effizienteste. Warum er aber den Index über (V2FARBE, V2FERTIGARTIKEL) statt nur über (V2FERTIGARTIKEL), kann ich dir auch nicht sagen. Vermutlich nimmt er einfach den erstbesten Index, mit dem er etwas anfangen kann. |
AW: Ausführunsplan / SQL Optimizer
Es gibt nur einen Index auf der Tabelle 'v2ps' und einen auf der Tabelle 'v2fertigartikel'. Es gibt keinen Index nur auf der Spalte 'v2ps.V2FertigArtikelId', also bleibt ihm nichts anderes übrig, als diesen V2PS_IDX3 Index zu verwenden. Oder, der exilant hat uns was verheimlicht.
|
AW: Ausführunsplan / SQL Optimizer
Achso, ich dachte ich hätte irgendwo gelesen, dass es noch einen separaten Index gäbe. Aber dann ist das ja auch geklärt.
|
AW: Ausführunsplan / SQL Optimizer
Vielen Dank für euer Interesse an meinem Problem. Mit der Erklärung über die Verwendung der Indexe bin ich jedoch nicht einverstanden. Warum mir ein Index auf dem _Feld_ V2FERTIGARTIKEL in der _Tabelle_ V2PS dabei helfen können soll, die passende Ergebnismenge aus gejointen _Tabelle_ V2FERTIGARTIKEL zu holen erschließt sich mir nicht. Tut es im übrigen ja auch nicht wie die Statistik zeigt.
Wenn ich das Query ohne JOIN auf die Auftragstabelle loslasse, also nur die Sätze aus der V2PS die den gewünschten Stati entsprechen Abfrage, bekomme ich den erwarteten Plan und die erwartete Anzahl indexierte Reads: PLAN (V2PS INDEX (V2PS_IDX1)) -> Das ist der Index auf das Feld STATUS Statistik: Reads indexed = 864 -> Entspricht der Anzahl der Sätze in der Menge. Durch Auswerten der WHERE Klausel kommt man schnell drauf, das es auf das Feld STATUS einen Index gibt. Genau den benutzt er auch. Alles OK. Gibt es aber das JOIN, so verwendet er keine sinnvollen Indexe mehr. Das zeigt die Statistik eindeutig. Wieso und warum er das tut sei jetzt mal dahingestellt. Die Indexe der Tabelle geben es geradezu Lehrbuchhaft her, einen optimalen Suchlauf zu starten. Sowohl die Statistik als auch der Plan zeigen klar, dass der Optimizer seine Arbeit nicht tut. Er verwendet - obwohl vorhanden - keinen sinnvollen Index und liest bei der einen Tabelle den gesamten Index durch (240.000 indexed reads) und die andere Tabelle komplett natural (7700 not indexed reads). Klarer kann ein Optimizer wohl nicht scheitern. Dieses Beispiel finde ich im übrigen noch sehr trivial.Wenn der Optimizer daran scheitert möchte ich nicht wissen was er mit wesentlich komplexeren Abfragen veranstaltet. Ich werde mir mal ein paar andere Sachen ansehen. Grüße, Martin |
AW: Ausführunsplan / SQL Optimizer
Zitat:
|
AW: Ausführunsplan / SQL Optimizer
Zitat:
Das soll nicht heißen, das Du zu blöd bist (also jetzt wirklich nicht mißverstehen), aber dreh den Spieß einfach mal um, gehe davon aus, das die anderen (Namenloser und der FB-Optimizer) Recht haben und Du dazulernen musst. Ich habe das in dieser Runde auch gemacht. Erzeuge andere Index und prüfe, wie der Optimizer sich dann verhält. Lies bei Firebird.org, wie der Optimizer das macht (gibts bestimmt irgendwo ein Whitepaper dazu). Oder vertraue einfach darauf, dass das RDBMS 'das schon machen wird'. Ich arbeite mit SQL-Server und muss nur 1x pro Jahr dem Optimizer mit einem Hint auf die Sprünge helfen (oder die Statistiken mal auf den neuesten Stand bringen). Ansonsten ist mir das doch wurscht, wie der mir die Daten liefert. Wenns nicht sofort kommt, prüfe ich, wieso und tune meine Query. Meistens kann man noch was rauskitzeln. Nur bloß keinen neuen Index (Antipattern: Index shotgun) |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Es handelt sich wie gesagt um Tabellen mit lehrbuchmäßigen Indexen und einer trivialen Query. Wenn der Optimizer es für optimal hält einen Index komplett zu lesen und eine andere Tabelle ohne Index "natural" komplett durchzugehen dann kann ich davon ausgehen dass es in der algorithmischen Welt des Optimizers eben nicht optimal zugeht... @Dejan Vu: Natürlich bin ich hier um zu lernen. Selbstverständlich habe ich an der Qualität von Firebird keine Zweifel. Ich benutze ihn seit es ihn gibt. Und ich bin mehr als zufrieden damit. Weiterhin bin ehrlich dankbar für jede Antwort die ich in diesem Thread erhalten habe und habe mich auch mit jeder Antwort auseinandergesetzt. Allerdings halte ich mich nicht für verbohrt weil ich das Ergebnis eines SQL Optimizers für fragwürdig halte. Grüße, Martin |
AW: Ausführunsplan / SQL Optimizer
Dann Teste doch einfach mit 2 größeren Testtabellen, dann siehst Du, ob das Verhalten den wenigen Werten geschuldet ist.
|
AW: Ausführunsplan / SQL Optimizer
Zitat:
Zitat:
Zitat:
Meist ist der Flaschenhals die übertragene Datenmenge und nicht die Abfrage als solche. Wenn's mit dem Tempo klemmt, dann sollte man schon schauen, ob das was man da nachfragt auch sinnvoll ist. Gruß K-H |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Woher willst Du denn eigentlich wissen, das das nicht die beste Strategie ist? Du denkst Dir das nur, aber bis ich hier einen Beweis sehe, glaube ich dem Optimizer, ehrlich gesagt, denn der rechnet wenigstens. Mach doch mal Folgendes: Kopiere die Tabellen einfach und erzeuge die in deinen Augen optimalen Indexe, aber vermeide oder deaktiviere den Index, der in deinen Augen vom Optimizer falsch verwendet wird und bringe den Optimizer einfach dazu, dir zu gehorchen. Dann vergleiche die beiden I/O-Statistiken. Vielleicht wird man schlau draus und tritt die Schlichtheit des Optimizers doch in die Tonne. Glauben kann Jeder (macht die Menschheit auch überwiegend). Aber *wissen* und *beweisen* machen wenige. |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Und es führt zu einem sehr guten Ergebnis: Ich habe hier eine Datenbank rumliegen in der Messwerte gespeichert werden. Die habe ich zu während des Nachmittags zu testzwecken mal Aktiviert und meine Auftragsdaten reingeschoben (macht in deisem Kontext zwar keinen Sinn, ist aber schön zum testen). Soeben war der Batch fertig. Ich habe dann sofort getestet. In der DB gibt es eine Tabelle mit der stolzen Anzahl von 74.530.307 Sätzen. Ein Feld im Messdatensatz enthält einen Schlüssel aus meiner Auftragsdatei (wie gesagt ca. 240.000 Sätze). Und siehe da: Es wird ein optimaler Plan gebaut. select mwrestfeuchte.par, v2ps.status from mwrestfeuchte inner join v2ps on (mwrestfeuchte.par=v2ps.par) where v2ps.status in ('A','U') Auch hier sind die Indexe lehrbuchmäßig. Und siehe da: Er verwendet für beide Tabellen den optimalen index und die Statistik ist sehr gut aus: PLAN JOIN (V2PS INDEX (V2PS_IDX1, V2PS_IDX1), MWRESTFEUCHTE INDEX (MWRESTFEUCHTE_IDX1)) Indexed Reads mwrestfeuchte: 4680 Indexed Reads v2ps: 12 Also an Namenloser, Dejan Vu und all' die anderen: Es ist zu vermuten, dass der Optimizer je nach Tabellengröße "abwägt" wann er "wirklich" was tut. Sehr beruhigend. Und nochmal vielen Dank an alle. Grüße, Martin |
AW: Ausführunsplan / SQL Optimizer
Zitat:
Danke, Martin |
AW: Ausführunsplan / SQL Optimizer
Der Programmteil im Compiler (der aus einem SELECT einen ausführbare Struktur erzeugt), nennt sich ja 'Optimizer'. Der optimiert wirklich, d.h. er wählt anhand der Index- und I/O-Statistiken (und diversen anderen Werten) den vermeidlich optimalen Ausführungsplan aus. Das geht meist über Brute-Force, d.h. der Algorithmus probiert nicht alle Kombinationen durch. Trotzdem dauert es ein paar ms, bis der Plan fertig ist, weswegen es sich lohnt, seine aus der Anwendungen kommenden Anweisungen per 'prepare' vorzukompilieren. Dann wird einmalig ein Query-Plan angelegt.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz