Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erläuterung des Leistungstests von Python ORM basierend auf dem TPC-C-Benchmark

Detaillierte Erläuterung des Leistungstests von Python ORM basierend auf dem TPC-C-Benchmark

coldplay.xixi
coldplay.xixinach vorne
2020-07-28 16:57:283060Durchsuche

Detaillierte Erläuterung des Leistungstests von Python ORM basierend auf dem TPC-C-Benchmark

Wenn die Anwendung zusammen mit der Datenbank verwendet werden muss, wird in der Python-Programmierung normalerweise der Object Relationship Maper (ORM) verwendet. Beispiele für Python-ORMs sind SQLAlchemy, Peewee, Pony-ORM und Django. Die Wahl der ORM-Leistung spielt eine entscheidende Rolle. Aber wie vergleichen sich diese Toolsets? ORM-Leistungsbenchmarks liefern einen klaren Maßstab, aber es gibt noch viel Raum für Verbesserungen. Ich habe qualitative ORM-Benchmarks recherchiert und erweitert, um Entwicklern in Not zu helfen. Der qualitative Python-ORM-Benchmark Tortoise ORM (Link zum Repository) analysiert die Geschwindigkeit von sechs ORMs für 11 Arten von SQL-Abfragen.

Verwandte Lernempfehlungen:

Python-Video-Tutorial

Normalerweise kann der Tortoise-Benchmark die Abfrageausführungsgeschwindigkeit verschiedener ORMs bewerten. Diese Testmethode weist jedoch einen Fehler auf: Die meisten ORMs werden für Webanwendungen ausgewählt. In diesem Fall senden häufig mehrere Benutzer unterschiedlichste Abfragen an die Datenbank. Da es keine evaluierten Benchmarking-Tools gibt, mit denen sich die Leistung von Python ORM in diesem Zusammenhang bewerten lässt, habe ich beschlossen, zum Vergleich mein eigenes PonyORM und SQLAlchemy zu schreiben. Als Basis habe ich den TPC-C Benchmark verwendet.

Seit 1988 entwickelt und testet TPC im Bereich der Datenverarbeitung. Sie sind längst zum Industriestandard geworden und werden von fast allen Geräteherstellern auf verschiedenen Hardware- und Softwarebeispielen eingesetzt. Das Hauptmerkmal dieser Tests besteht darin, dass sie sich auf Tests unter großen Belastungen konzentrieren, die den realen Bedingungen möglichst nahe kommen.

 TPC-C simuliert ein Lagernetzwerk. Es besteht aus einer Kombination von fünf Transaktionen unterschiedlicher Art und Komplexität, die gleichzeitig ausgeführt werden. Der Zweck dieses Tests besteht darin, die Geschwindigkeit der Transaktionsverarbeitung zu bewerten, wenn mehrere virtuelle Benutzer gleichzeitig auf die Datenbank zugreifen.

Ich habe beschlossen, zwei Python-ORMs (SQLALchemy und PonyORM) mit der für diese Aufgabe geeigneten TPC-C-Testmethode zu testen. Der Zweck dieses Tests besteht darin, die Geschwindigkeit der Transaktionsverarbeitung zu bewerten, wenn mehrere virtuelle Benutzer gleichzeitig auf die Datenbank zugreifen.

Testanweisungen

Der erste Schritt besteht darin, die Datenbank des Lagernetzwerks zu erstellen und zu füllen.

Die Datenbank enthält acht Beziehungen:

1. Lager

2. Bezirk

3. Auftrag

4. Auftragszeile

5. Aktien

6. Projekte

7. Kunden

8. Geschichte

Die Datenbanken von Pony und SQLAlchemy sind identisch . Es werden nur Primär- und Fremdschlüssel indiziert. Little A erstellt diese Indizes automatisch. In SQLAlchemy habe ich es manuell erstellt.

Während des Tests haben mehrere virtuelle Benutzer verschiedene Arten von Transaktionen an die Datenbank gesendet. Jede Transaktion enthält mehrere Anfragen. Es werden insgesamt fünf Arten von Transaktionen mit unterschiedlicher Eintrittswahrscheinlichkeit zur Bearbeitung eingereicht:

Transaktionen:

1. Neue Bestellungen – 45 %

2. Zahlung – 43 %

 3. Bestellstatus-4%

 4. Lieferung-4%

 5. Lagerbestand-4%

  Wahrscheinlichkeit, dass eine Transaktion stattfindet, im Vergleich zum Original TPC – Dasselbe wie im C-Test.

Bitte bedenken Sie jedoch, dass aufgrund technischer Einschränkungen und weil ich die Leistung der folgenden Prozessoren testen wollte, das Original auf einem Server mit 64+ GB RAM erstellt wurde (was viele Prozessoren und mehr erfordert). riesiger Speicherplatz) TPC-C-Test. Das ORM und nicht die Fähigkeit der Hardware, großen Belastungen standzuhalten, daher ist dieser Test etwas vereinfacht.

Die Hauptunterschiede zum TPC-C-Test sind wie folgt:

Die Hauptunterschiede:

1. Dieser Test führt weniger virtuelle Benutzer durch als der ursprüngliche Test

2 . Mein Test hat weniger Tabelleneinträge. Beispiel: Die Anzahl der Einträge in der Beziehung „Bestand“ im ursprünglichen Test wurde mit der Formel 100.000 * W berechnet, wobei W die Anzahl der Lager ist. In diesem Test sind es 100*W.

 3. In TPC-C verfügen einige Transaktionen über mehrere Optionen zum Abfragen von Daten aus der Datenbank. Beispielsweise gibt es bei einem Zahlungsvorgang eine Möglichkeit, den Kunden per ID aus der Datenbank abzufragen, und eine andere per Nachname und Vorname. Derzeit telefoniert mein Test nur per ID.

 4. Meine Testdatenbank hat eine Tabelle weniger als TPC-C. Bei TPC-C-Tests wird eine Bestellung, nachdem sie erstellt wurde, der Order-Tabelle und der NewOrder-Tabelle hinzugefügt. Sobald die Bestellung geliefert wurde, wird sie aus der NewOrder-Tabelle gelöscht. Dies kann die Arbeit beschleunigen, wenn eine große Anzahl von Transaktionen pro Minute durchgeführt wird. Da jedoch weniger Benutzer auf die Datenbank zugreifen, ist dies nicht erforderlich. Stattdessen habe ich in der Order-Tabelle das bool-Attribut „is_o_delivered“ hinzugefügt, das False ist, bis die Bestellung geliefert wird.

Als nächstes werde ich kurz die Rolle jeder Transaktion beschreiben.

Anzahl der Transaktionen

Neuer Befehl

1. Übergeben Sie zwei Parameter an die Transaktion: Lager-ID und Kunden-ID

2. Verwenden Sie die übergebene ID von Wählen Sie das Lager und den Kunden aus der Datenbank aus

 3. Wählen Sie zufällig einen Lagerbereich aus der Datenbank aus

 4. Generieren Sie eine Zufallszahl, die die Anzahl der Auftragszeilen angibt.

 5. Erstellen Sie ein Auftragsobjekt

 6. Schleife zum Erstellen von OrderLine-Objekten. Wählen Sie bei jeder Iteration der Schleife einen zufälligen Artikel aus der Artikeltabelle aus

7. Ändern Sie den Bestand jedes Artikels in der Bestellung

Zahlung

1. Ändern Sie die beiden An die Transaktion übergebene Parameter: Lager-ID und Kunden-ID

2. Wählen Sie anhand der übergebenen ID das Lager und den Kunden aus der Datenbank aus

3. Wählen Sie zufällig einen Lagerbereich aus der Datenbank aus

4. Generieren Sie eine Zufallszahl, die den Zahlungsbetrag angibt

5. Erhöhen Sie den Saldo des Lagers und der Region um den Zahlungsbetrag

6. Verringern Sie den Kundensaldo um den Zahlungsbetrag

7. Erhöhen Sie den Kundenzahlungszähler

 8. Erhöhen Sie die Summe des Kundenzahlungsbetrags

 9. Erstellen Sie ein Verlaufsobjekt

 Bestellstatus

 1. Übergeben Sie die Kunden-ID als Transaktionsparameter von

2. Wählen Sie den Kunden anhand der ID und der letzten Bestellung des Kunden aus

3. Rufen Sie den Bestellstatus und die Bestellzeile aus der Bestellung ab.

Lieferung

1. Übergeben Sie die Lager-ID als Transaktionsparameter

2. Wählen Sie das Lager und alle seine Bereiche aus der Datenbank aus

3. Für jeden Die Region wählt die älteste nicht zugestellte Bestellung aus.

4. Für jede Bestellung, die den Lieferstatus auf „True“ ändert

5. Für jeden Kunden mit steigender Bestellmenge

Lagerbestand

1. Übergeben Sie die Lager-ID als Transaktionsparameter

2. Wählen Sie das Lager aus der Datenbank anhand der ID aus

3. Wählen Sie die letzten 20 Bestellungen des Lagers aus

4. Für die Bestellung Für Bewerten Sie für jedes Projekt den Lagerbestand des Projekts

Testergebnisse

An dem Test nehmen zwei ORMs teil:

1. SQLAlchemy (blaue Linie im Diagramm)

 2. PonyORM (orangefarbene Linie im Diagramm)

 Das Folgende sind die Ergebnisse einer 10-minütigen Testausführung durch Zugriff auf die Datenbank über zwei parallele Prozesse. Starten Sie den Prozess mit dem Multiprocessing-Modul.

Zuerst habe ich, wie im TPC-C-Test erwartet, alle fünf Transaktionen getestet. Das Ergebnis dieses Tests ist, dass die Geschwindigkeit von Little A etwa doppelt so hoch ist wie zuvor.

Durchschnittsgeschwindigkeit:

· Kleine A-2543 Transaktionen/Minute

· SQLAlchemy-1353,4 Transaktionen/Minute

Danach beschloss ich, fünf zu bewerten Transaktionen separat. Transaktions-ORM-Leistung. Nachfolgend finden Sie die Ergebnisse für jeden Handel.

Neuer Befehl

Durchschnittsgeschwindigkeit:

· Kleine A-3349,2 Transaktionen/Min.

· SQLAlchemy-1415,3 Transaktionen/Min.

Zahlung

Durchschnittsgeschwindigkeit:

Klein A-7175,3 Transaktionen/Minute

SQLAlchemy-4110,6 Transaktionen/Minute

Bestellstatus

Durchschnittlich Geschwindigkeit:

Klein A-16645,6 Transaktionen/Minute

SQLAlchemy-4820,8 Transaktionen/Minute

Lieferung

Durchschnittsgeschwindigkeit:

 · SQLAlchemy-716,9 Transaktionen/Minute

 · Kleine A-323,5 Transaktionen/Minute

 Bestandsniveau

 Durchschnittliche Geschwindigkeit:

 · Kleine A-677,3 Transaktionen/ Minute

SQLAlchemy-167.9 Transaktionen/Minute

Analyse der Testergebnisse

Nachdem ich die Ergebnisse erhalten hatte, analysierte ich, warum dies passierte, und kam zu folgendem Schluss:

Bei 4 von 5 Transaktionen ist PonyORM schneller, da sich PonyORM beim Generieren von SQL-Code die Ergebnisse der Konvertierung von Python-Ausdrücken in SQL merkt. Daher konvertiert Pony den Ausdruck nicht erneut, wenn die Abfrage wiederholt wird, während SQLAlchemy gezwungen ist, jedes Mal SQL-Code zu generieren, wenn die Abfrage ausgeführt werden muss.

Beispiel für eine solche Abfrage in Pony:

stocks = select(stock for stock in Stock
  if stock.warehouse == whouse
  and stock.item in items).order_by(Stock.id).for_update()

Generiertes SQL:

 SELECT “stock”.”id”, “stock”.”warehouse”, “stock”.”item”,
  “stock”.”quantity”, “stock”.”ytd”, “stock”.”order_cnt”,
  “stock”.”remote_cnt”, “stock”.”data”FROM “stock” “stock”WHERE “stock”.”warehouse” = %(p1)s
  AND “stock”.”item” IN (%(p2)s, %(p3)s)ORDER BY “stock”.”id”FOR UPDATE
  {‘p1’:7, ‘p2’:7, ‘p3’:37}
  SQLAlchemy:
  stocks = session.query(Stock).filter(
  Stock.warehouse == whouse, Stock.item.in_(
  items)).order_by(text(“id”)).with_for_update()

Generiertes SQL:

SELECT stock.id AS stock_id, stock.warehouse_id AS stock_warehouse_id,
  stock.item_id AS stock_item_id, stock.quantity AS stock_quantity,
  stock.ytd AS stock_ytd, stock.order_cnt AS stock_order_cnt,
  stock.remote_cnt AS stock_remote_cnt, stock.data AS stock_dataFROM stockWHERE stock.warehouse_id = %(warehouse_id_1)s AND stock.item_id IN
  (%(item_id_1)s, %(item_id_2)s) ORDER BY id FOR UPDATE
  {‘warehouse_id_1’: 7, ‘item_id_1’: 53, ‘item_id_2’: 54}

Allerdings kann SQLAlchemy natürlich schneller sein Ausführung von Übermittlungstransaktionen, da mehrere UPDATE-Vorgänge, die auf verschiedene Objekte angewendet werden, in einem einzigen Befehl kombiniert werden können.

Beispiel:

INFO:www.zpedu.com/sqlalchemy.engine.base.Engine:UPDATE order_line SET delivery_d=%
  (delivery_d)s WHERE order_line.id = %(order_line_id)s
  INFO:sqlalchemy.engine.base.Engine:(
  {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922281),
  ‘order_line_id’: 316},
  {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922272),
  ‘order_line_id’: 317},
  {‘delivery_d’: datetime.datetime(2020, 4, 6, 14, 33, 6, 922261))

In diesem Fall sendet Little A für jedes Update eine separate Anfrage.

Fazit

Anhand der Testergebnisse kann ich sagen, dass Pony schneller aus der Datenbank auswählt. Andererseits kann SQLAlchemy in einigen Fällen Abfragen vom Typ Update mit einer höheren Geschwindigkeit generieren.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Leistungstests von Python ORM basierend auf dem TPC-C-Benchmark. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen