Wie kann ich eine bestimmte Anzahl von Zeilen auswählen, zB "so viele Zeilen wie möglich in 5 Sekunden holen"?

7

Ziel ist es, nach 5 Sekunden die höchste Anzahl von Zeilen zu erhalten und nicht mehr Zeilen als Zeilen zu bekommen. Das Ziel ist kein Timeout.

Nach Monaten dachte ich, das würde vielleicht funktionieren und das nicht:

%Vor%     
Uğur Gümüşhan 11.12.2011, 15:35
quelle

5 Antworten

27

Obwohl sich der Trend in den letzten Jahren für relationale Datenbanken mehr und mehr auf kostenbasierte Abfrageoptimierung verlagert hat, gibt es kein bekanntes RDBMS, das inhärent die Festlegung von maximalen Kosten (in Zeit oder I / O) für eine Abfrage unterstützt .

Die Idee "Lass es einfach ausklingen und nutze die bisher gesammelten Aufzeichnungen" ist eine fehlerhafte Lösung. Der Fehler liegt in der Tatsache, dass eine komplexe Abfrage die ersten 5 Sekunden damit verbringen kann, einen Hash in einem Teilbaum des Abfrageplans auszuführen, um Daten zu generieren, die von einem späteren Teil des Plans verwendet werden. Nach 5 Sekunden haben Sie vielleicht noch keine Aufzeichnungen.

Um innerhalb von 5 Sekunden die meisten Datensätze möglich zu machen , benötigen Sie eine Abfrage mit einem bekannten geschätzten Ausführungsplan, der dann verwendet werden könnte, um die optimale Anzahl der Datensätze zu ermitteln, die angefordert werden Lassen Sie die Abfrage so lange wie möglich für 5 Sekunden laufen. Mit anderen Worten, wenn Sie wissen, dass der Abfrageoptimierer schätzt, dass er 875 Datensätze pro Sekunde verarbeiten kann, können Sie 4.375 Datensätze anfordern. Die Abfrage läuft manchmal etwas länger als 5 Sekunden, aber im Laufe der Zeit sollte die durchschnittliche Ausführung fast 5 Sekunden dauern.

Also ... wie kann ich das erreichen?

In Ihrer speziellen Situation ist es nicht machbar. Der Fang ist "bekannter geschätzter Ausführungsplan". Damit dies zuverlässig funktioniert, benötigen Sie eine gespeicherte Prozedur mit einem bekannten Ausführungsplan und keine Ad-hoc-Abfrage. Da Sie in Ihrer Umgebung keine gespeicherten Prozeduren erstellen können, ist das kein Problem. Für andere, die diese Lösung jedoch erforschen möchten, ist hier eine akademische Arbeit von einem Team, das implementiert wurde, Dieses Konzept in Oracle. Ich habe das vollständige Papier nicht gelesen, aber basierend auf dem Abstract klingt es, als ob ihre Arbeit in jedes RDBMS übersetzt werden könnte, das kostenbasierte Optimierung hat (zB MS SQL, MySQL, etc.)

OK, was können Sie in Ihrer Situation tun?

Wenn Sie es nicht "richtig" machen können, lösen Sie es mit einem Hack.

Mein Vorschlag: Behalte deine eigenen geschätzten Kosten.

Machen Sie vorab einige Tests und schätzen Sie, wie viele Zeilen Sie normalerweise in 4 Sekunden zurückbekommen. Sagen wir, diese Zahl ist 18.000.

Also limitieren Sie Ihre Abfrage auf 18.000 Zeilen. Aber Sie verfolgen auch die Ausführungszeit jedes Mal, wenn Sie es ausführen, und behalten Sie einen gleitenden Durchschnitt von, sagen wir, die letzten 50 Ausführungen. Wenn dieser Durchschnitt weniger als 4,5 s beträgt, fügen Sie der Abfragegröße 1% hinzu und setzen Sie den gleitenden Durchschnitt zurück. Nun fordert Ihre App jedes Mal 18.180 Zeilen an. Fügen Sie nach 50 Iterationen, wenn der gleitende Durchschnitt unter 4.5s liegt, erneut 1% hinzu.

Und wenn Ihr gleitender Durchschnitt 4,75s überschreitet, ziehen Sie 1% ab.

Im Laufe der Zeit sollte diese Methode zu einer optimierten N-Zeilen-Lösung für Ihre spezielle Abfrage / Umgebung / etc konvergieren. Und sollte (langsam, aber stetig) angepasst werden, wenn sich die Bedingungen ändern (z. B. starke Nebenläufigkeit gegenüber geringer Nebenläufigkeit)

Nur eins - kratze das, zwei - noch mehr ...

  1. Als DBA muss ich sagen ... es sollte äußerst selten sein, dass eine Abfrage mehr als 5 Sekunden dauert. Insbesondere, wenn es sich um eine Abfrage handelt, die häufig ausgeführt wird und von der Front-End-Anwendung verwendet wird, sollte absolut nicht für 5 Sekunden ausgeführt werden. Wenn Sie wirklich eine benutzerbezogene Abfrage haben, die nicht innerhalb von 5 Sekunden abgeschlossen werden kann, ist dies ein Zeichen dafür, dass das Datenbankdesign verbessert werden muss.

  2. Der Law Of The Greenbar-Bericht von Jonathan VM Früher habe ich für ein Unternehmen gearbeitet, das immer noch eine Mainframe-Anwendung verwendete, die jeden Tag unzählige grüne Punktmatrix-Berichte ausspuckte. Die meisten wurden ignoriert, und von den wenigen, die verwendet wurden, wurden die meisten nie über die erste Seite hinaus gelesen. Ein Bericht könnte Tausende von Zeilen haben, sortiert nach dem Alter des absteigenden Kontos ... und alles, was der Benutzer brauchte, war, die 10 am meisten gealterten zu sehen. Mein Gesetz ist das: Die Anzahl der Anwendungsfälle, die tatsächlich eine große Anzahl von Zeilen sehen müssen, ist infinitesimal klein. Denke - denke wirklich - über den Anwendungsfall für deine Anfrage und ob es sehr viele davon gibt Datensätze sind wirklich was der Benutzer braucht.

Jonathan Van Matre 16.12.2011 17:58
quelle
5

Ihre While-Loop-Idee löst das Problem nicht vollständig. Es ist möglich, dass die erste Iteration durch die Schleife länger als 5 Sekunden dauern könnte. Außerdem wird es wahrscheinlich dazu führen, dass in der zugewiesenen Zeit weit weniger Zeilen abgerufen werden, als wenn Sie es nur mit einer einzigen Abfrage versuchen würden.

Persönlich würde ich nicht versuchen, dieses genaue Problem zu lösen. Stattdessen würde ich einige Tests durchführen und durch Versuch und Irrtum eine Reihe von Datensätzen identifizieren, von denen ich sicher bin, dass sie in weniger als fünf Sekunden geladen werden. Dann würde ich einfach eine LIMIT auf die Ladeanfrage setzen.

Als nächstes setze ich je nach den Anforderungen entweder einen Timeout für den DB-Aufruf von fünf Sekunden oder lebe mit der Möglichkeit, dass einige Anrufe die Zeitbeschränkung überschreiten.

Beachten Sie, dass Sie bei den meisten Abfragen auf der modernsten Hardware innerhalb von fünf Sekunden eine sehr große Anzahl von Datensätzen zurückgeben können. Es ist schwer vorstellbar, all diese Daten an die Benutzeroberfläche zurückzugeben und sie trotzdem nutzbar zu machen, wenn dies Ihre Absicht ist.

-Jason

    
jmacinnes 11.12.2011 15:46
quelle
0

Ich habe das nie ausprobiert, aber wenn ein Skript diese Abfrage ausführt, könnten Sie versuchen, eine ungepufferte Abfrage auszuführen (in PHP wäre dies etwa wie mysql_unbuffered_query ()) ... Sie könnten diese dann währenddessen in einem Array speichern Die Abfrage wird ausgeführt. Sie könnten dann das mysql-Abfrage-Timeout auf fünf Minuten setzen. Wenn die Abfrage beendet wird und Sie Ihre while () -Schleife so eingerichtet haben, dass sie nach einer Zeitüberschreitungserwiderung sucht, kann sie die Schleife beenden und Sie erhalten innerhalb von 5 Minuten ein Array mit allen zurückgegebenen Datensätzen. Ich bin mir nicht sicher, ob das funktionieren würde, aber es würde mich interessieren zu sehen, ob es das erreichen wird, was Sie anstreben.

    
Ben D 15.12.2011 22:31
quelle
0

Sie könnten dieses Problem so angehen, aber ich bezweifle, dass diese Logik wirklich ist, was ich für den realen Gebrauch empfehlen würde.

Sie haben ein 10s Intervall, Sie versuchen eine Abfrage, es bringt Ihnen die Zeile in 0.1s. Das würde bedeuten, dass Sie in den verbleibenden 9,9 s noch mindestens 99 ähnliche Anfragen erhalten könnten. 99 Abfragen auf einmal sollten jedoch schneller sein, als sie nacheinander zu erhalten (was Ihre anfängliche Berechnung nahelegen würde). So erhalten Sie die 99 Abfragen und überprüfen Sie die Zeit erneut.

Nehmen wir an, die Operation wurde 1,5-mal so schnell ausgeführt wie die einzelne Abfrage, weil es effizienter ist, mehr Abfragen gleichzeitig zu erstellen, sodass Sie zu einem Zeitpunkt von 7,5 s mit 100 Zeilen auskommen. Sie berechnen, dass Sie im Durchschnitt bis zu 100 Zeilen pro 7,5 s erhalten haben, berechnen Sie eine neue Menge von möglichen Abfragen für den Rest der Zeit und Abfrage erneut, und so weiter. Sie müssten jedoch einen Schwellenwert für diese Schleife festlegen, sagen wir mal so etwas wie: Keine neuen Abfragen mehr nach 9.9s.

Diese Lösung ist offensichtlich weder die glatteste noch die, die ich wirklich verwenden würde, aber vielleicht dient sie dazu, das Problem des OP zu lösen. Jmainnes hat bereits darauf hingewiesen: "Es ist möglich, dass die erste Iteration durch die Schleife länger als 10 [5] Sekunden dauern kann."

Ich würde mich selbst sicherlich interessieren, wenn jemand eine angemessene Lösung für dieses Problem finden kann.

    
kontur 16.12.2011 14:10
quelle
0

Um Daten aus der Tabelle zu erhalten, sollten Sie zwei Dinge tun:

  1. Führe eine Abfrage aus (SELECT something FROM table)
  2. füllen Sie die Tabelle aus oder Daten lesen

Sie fragen nach dem zweiten. Ich bin nicht so vertraut mit PHP, aber ich denke, es spielt keine Rolle. Wir verwenden das Abrufen, um die ersten Datensätze schnell zu erhalten und sie dem Benutzer anzuzeigen, und dann Datensätze nach Bedarf abzurufen. In ADO.NET könnten Sie IDataReader verwenden, um Datensätze einzeln zu erhalten, in PHP denke ich, dass Sie ähnliche Methoden verwenden könnten, zum Beispiel - mysqli_fetch_row in der mysqli-Erweiterung oder mysql_fetch_row in mysql-Erweiterung. In diesem Fall könnten Sie jederzeit aufhören, Daten zu lesen.

    
Devart 16.12.2011 14:10
quelle

Tags und Links