Frage

Ich lese Hadoop: The Definitive Guide von Tom White. In Kapitel 13.6 „HBase vs RDMS“, sagte er, dass, wenn Sie eine Menge Daten haben, auch einfache Abfragen wie 10 Neueinträge bekommen extreamly teuer sind und sie hatten sie neu zu schreiben, mit Python und PL / SQL.

Er gibt die folgende Abfrage als Beispiel:

SELECT id, stamp, type FROM streams 
WHERE type IN ('type1','type2','type3','type4',...,'typeN')
ORDER BY stamp DESC LIMIT 10 OFFSET 0;

Und sagt: „ein RDBMS Anfrageplaner behandelt diese Abfrage wie folgt:

MERGE (
  SELECT id, stamp, type FROM streams
    WHERE type = 'type1' ORDER BY stamp DESC,
  ...,
  SELECT id, stamp, type FROM streams
    WHERE type = 'typeK' ORDER BY stamp DESC
) ORDER BY stamp DESC LIMIT 10 OFFSET 0;
  

Das Problem hier ist, dass wir nach sind   nur der Top-10-IDs, aber die Abfrage   Planer materialisiert eigentlich ein   gesamte merge und dann an den Grenzen   Ende. .... Wir gingen sogar so weit,   eine benutzerdefinierte PL / Python-Skript zu schreiben   die durchgeführt einen Heapsort. ... Im   fast allen Fällen besser als diese   die native SQL-Implementierung und die   Anfrageplaner Strategie ...

Erwartete perforamnce und expermiental Ergebnisse

Ich konnte nicht den Datensatz vorstellen, dass solche Probleme verursachen wird, dass Sie schreiben müssen pl / Python so einfache Abfrage richtig zu machen. So habe ich eine Zeit lang über dieses Problem gespielt und kam mit folgenden Beobachtungen auf:

Die Leistung einer solchen Abfrage wird durch O (KlogN) begrenzt werden. Weil es kann so etwas wie folgt übersetzt werden:

SELECT * FROM (
  SELECT id, stamp, type FROM streams
    WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10,
  UNION
  ...,
  SELECT id, stamp, type FROM streams
    WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10
) t ORDER BY stamp DESC LIMIT 10;

(beachten Sie das ‚LIMIT 10‘ bei jeder Abfrage. BTW weiß ich, dass ich nicht und Ordnung Gewerkschaften beschränken kann, aber ich habe aus Gründen der Lesbarkeit Verpackung wählt gezupft)

Jede Unterabfrage sollte so schnell laufen wie die richtige Postion in einem Index O (log N) zu finden und 10 Einzelteile zurückbringen. Wenn wir das K-mal wiederholen bekommen wir O (KlogN).

Und selbst wenn Anfrageplaner so schlecht, dass es nicht die erste Abfrage optimieren kann wir es auf die Abfrage mit den Gewerkschaften immer übersetzen können und die gewünschte Leistung erhalten, ohne etwas zu schreiben in pl / Python.

verdoppeln meinen Berechnungen überprüfen Ich habe die Abfragen über eine postgresql mit 9.000.000 von Testsätzen gefüllt laufen. Die Ergebnisse bestätigten meine Erwartungen beide Abfragen recht schnell 100ms für die erste Abfrage und 300ms für die zweite (die mit Gewerkschaften) waren.

Wenn also die Abfrage läuft in 100ms für 9.000.000 (log n = 23) der Datensätze dann für 9000000000 (log n = 33) von Datensätzen in 140ms ausgeführt werden soll.

Fragen

  • Haben Sie Fehler in oben Argumentation sehen?
  • Können Sie einen Datensatz vorstellen, wo Sie eine solche Abfrage, wie oben in pl / Python?
  • neu zu schreiben, müssten
  • Sehen Sie eine Situation, in der eine solche Abfrage nicht funktionieren würde in O (K log n)?
War es hilfreich?

Lösung

Die Behauptung, dass ein RDMBS Anfrageplaner, dass die Lösung für die Abfrage dauert ist falsch, zumindest für Postgresql 9.0, und ich soll für andere Plattformen denken. Ich habe einen Schnelltest mit einer ähnlichen Abfrage:

explain select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by client_attribute_id desc limit 10;

                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..0.93 rows=10 width=85)
   ->  Index Scan Backward using client_attribute_pkey on client_attribute  (cost=0.00..15516.47 rows=167234 width=85)
         Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))
(3 rows)

Hier client_attribute_id indiziert ist, so dass es genau funktioniert wie desired- durch den Index geht zurück, wendet den Filter und stoppt, wenn der Ausgang der Grenze trifft.

Wenn die Bestellung Spalte nicht indiziert ist, eine Tabellensuche und Sortierung ist requierd, aber nur ein Tabelle-Scan:

explain analyze select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by updated desc limit 10;

                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=13647.00..13647.03 rows=10 width=85) (actual time=180.961..180.964 rows=10 loops=1)
   ->  Sort  (cost=13647.00..14065.09 rows=167234 width=85) (actual time=180.960..180.961 rows=10 loops=1)
         Sort Key: updated
         Sort Method:  top-N heapsort  Memory: 26kB
         ->  Seq Scan on client_attribute  (cost=0.00..10033.14 rows=167234 width=85) (actual time=0.010..106.791 rows=208325 loops=1)
               Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))

Dabei wird ein Heapsort der Top-10-Ergebnisse durch den Verlauf des sequentiellen Scan zu halten, was genau klingt wie die Lösung, die sie selbst geschrieben hat.

Andere Tipps

Ich glaube nicht, dass Tom White sagt, dass relationale Datenbanken sind „schlecht“; sie sind nicht optimal für die nicht-relationalen, nicht-Satz basierter Daten.

Es ist seit langem bekannt, dass tief Objektgraphen eignen sich nicht gut auf relationale Datenbanken. Sie sind typischerweise in Problemen wie CAD-Darstellungen von geometrischen Daten, in denen Baugruppen bestehen aus Anordnungen von Baugruppen von Teilen gefunden. Die Referenzketten sind sehr lang, in der Tat.

Objekt- und Graphdatenbanken haben auf diese Art von Problemen die Lösungen gewesen, da mir bewusst war sie in den frühen 90er Jahren.

Relationale Datenbanken sind grandios für relationale, Set-basierte Daten. Aber alle Daten fallen nicht in diese Kategorie. Deshalb NoSQL ist Geist Anteile zu gewinnen.

Ich denke, das ist, was das Beispiel, das Sie zitieren sagt.

ist RDBMS für die Fragen, die Sie nicht gedacht haben. Sobald Sie genau sicher sind, was Sie wollen, können Sie dann die optimalste Lösung gelten.

Mit entweder SQL oder NoSQL, wird die Leistung schrecklich sein, wenn Sie Ihre Fragen in der falschen Art und Weise entwerfen.

Ich würde dieses Beispiel beheben, indem Sie einen Scheck auf Zeitstempel auf die where-Klausel hinzugefügt wird. Wenn Sie eine Menge von Daten haben, können Sie wahrscheinlich davon ausgehen, dass die letzten 10 Einträge aus der letzten Minute sind - warum also versuchen, das Lesen und Sortieren alles vom letzten Monat

Ich könnte genauso gut das gleiche Beispiel ersinnen zu NoSQL schlecht aussehen zu machen, indem sie behaupten, dass, weil Sie standardmäßig nur die Datensätze von ID finden Sie den gesamten Datensatz geladen werden müssen, um den Datensatz, den Sie finden müssen, ohne auf die Möglichkeit, Set verschiedene sekundäre / benutzerdefinierte Indizes, die Sie wird besser als SQL-Performance für die Abfragen, die Materie.

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