Die einzige Art, wie ich auf field4
einen Index (a) wäre haben diese Art von Unterschied in der Ausführungsgeschwindigkeit zu bekommen denken kann, und (b) einen viele von leeren Datenblöcken; möglicherweise von einer hohen Wassermarke, die durch wiederholte Direktweglasten sehr hoch eingestellt ist.
Die erste Abfrage würde immer noch den Index verwenden und wie erwartet ausführen. Da Nullwerte jedoch nicht indiziert sind, kann der Index nicht zur Überprüfung der or field4 is null
-Bedingung verwendet werden, sodass er auf einen vollständigen Tabellenscan zurückfällt.
Das sollte an sich kein Problem sein, da ein vollständiger Tabellenscan von 7000 Zeilen nicht lange dauern sollte. Aber seit es so lange dauert, ist etwas anderes los. Ein vollständiger Tabellenscan muss jeden der Tabelle zugewiesenen Datenblock untersuchen, um zu sehen, ob sie Zeilen enthalten, und die dafür benötigte Zeit lässt darauf schließen, dass selbst bei Inline-CLOB-Speicher mehr Blöcke als 7000 Zeilen vorhanden sind.
Der einfachste Weg, um viele leere Datenblöcke zu bekommen, ist, eine Menge Daten zu haben und dann den größten Teil davon zu löschen. Aber ich glaube, Sie haben in einem jetzt gelöschten Kommentar zu einer früheren Frage gesagt, dass die Leistung früher in Ordnung war und sich verschlechtert hat. Das kann passieren, wenn Sie direct-path inserts tun, insbesondere wenn Sie Daten "löschen", indem Sie sie löschen und dann neue Daten im Direktpfad-Modus einfügen. Sie könnten das mit Inserts tun, die den /*+ append */
Hinweis haben; oder parallel; oder über SQL * Loader. Jedes Mal, wenn Sie das tun, würde sich die Hochwassermarke bewegen, da alte leere Blöcke nicht wiederverwendet werden würden; und jedes Mal würde sich die Leistung der Abfrage, die auf Nullen prüft, etwas verschlechtern. Nach vielen Iterationen würde das wirklich beginnen sich zu summieren.
Sie können das Datenwörterbuch überprüfen, um zu sehen, wie viel Platz Ihrer Tabelle zugewiesen ist (user_segments
usw.), und vergleichen Sie das mit der Größe der Daten, die Sie tatsächlich denken. Sie können die HWM zurücksetzen, indem Sie die Tabelle neu erstellen, z.g by doing: (! vorzugsweise in einem Wartungsfenster)
alter table mytable move;
Als Demo lief ich einen Zyklus Einsatz zu leiten Pfad und löschen 7000 Zeilen über hundertmal, und dann liefen beide Ihre Fragen . Der erste dauerte 0,06 Sekunden (viel davon ist SQL Devleoper Overhead); der zweite dauerte 1.260. (Ich fuhr auch Gordon, der eine ähnliche Zeit bekam, da es immer noch eine FTS zu tun hat). Mit mehr Iterationen würde der Unterschied noch stärker werden, aber ich hatte keinen Platz mehr ... Dann habe ich einen alter table move
gemacht und die zweite Abfrage erneut ausgeführt, was dann 0,05 Sekunden dauerte.
Führt die erste Abfrage auch einen vollständigen Tabellenscan durch oder gibt es einen Index für field4, den sie verwenden kann? Und wenn das der Fall ist, wurde die Tabelle wiederholt gelöscht (nicht abgeschnitten) und mit direkten Pfadeinfügungen neu gefüllt (d. H. Mit dem Hinweis '/ * + append * /')? –
Was ist mit Plan für die erste Abfrage? – nilsman
Die Bedingung 'IS NULL' ignoriert den Index, da NULL-Werte nicht indiziert werden können. Nun, Sie könnten den Optimierer mit einem konstanten Wert zusammen mit der Spalte NULLABLE während der Indizierung austricksen. Aber um im Rahmen Ihrer Frage zu antworten, wird Ihre zweite Abfrage nach einem ** FULL TABLE SCAN ** gehen, es sei denn, Sie führen den Optimierer wie zuvor beschrieben aus. Ihre erste Abfrage könnte die Indizes nutzen und FTS vermeiden. 1. Bitte posten Sie auch den Plan für die erste Abfrage. 2. Sind die Statistiken aktuell? –