paint-brush
Effizientes Backend, überlegene Leistung: Ein tiefer Einblick in die Optimierung von Webdienstenby@sergeidzeboev
958
958

Effizientes Backend, überlegene Leistung: Ein tiefer Einblick in die Optimierung von Webdiensten

Sergei Dzeboev8m2023/11/21
Read on Terminal Reader

Die Optimierung des Backends eines Webdienstes geht über die reine Verbesserung von Code und Algorithmen hinaus. Der Schlüssel zur Verbesserung der Serviceeffizienz liegt in der Optimierung der Datenbankinteraktionen. Dies kann durch die Feinabstimmung von ORM-Abfragen, die Verwendung flacher Datenklassen, die ordnungsgemäße Kategorisierung von Daten als „Heiß“, „Warm“ oder „Kalt“ und den Einsatz effektiver Caching-Strategien erreicht werden. Diese Schritte führen zu einem effizienteren, reaktionsschnelleren und leistungsfähigeren Webdienst.
featured image - Effizientes Backend, überlegene Leistung: Ein tiefer Einblick in die Optimierung von Webdiensten
Sergei Dzeboev HackerNoon profile picture
0-item


Bei der Optimierung des Backends eines Webservices geht es immer darum, dessen Leistung zu steigern. Ein wesentlicher Aspekt dabei ist die Beschleunigung der Datenverarbeitung. Dieser Prozess umfasst viele wichtige Verbesserungen, die darauf abzielen, Ressourcen effizienter zu nutzen und die Reaktionszeit des Systems auf Anfragen zu minimieren. In diesem Artikel werde ich mehrere bewährte Techniken vorstellen, die Ihren Webdienst erheblich beschleunigen können.


Worauf sollte man sich bei der Verbesserung konzentrieren?

Viele Programmierer konzentrieren sich in ihrem Bestreben, eine Anwendung schneller zu machen, auf die Optimierung des Codes und der Algorithmen sowie auf die Auswahl geeigneter Datenstrukturen und optimaler Abläufe. Dies führt in der Regel zu einer verbesserten Leistung, wobei sich häufig auch die Geschwindigkeit des optimierten Codes verbessert, jedoch nicht wesentlich.


Der bescheidene Anstieg ist auf die inhärente Geschwindigkeit von Speicheroperationen zurückzuführen und wesentliche Verbesserungen sind nicht zu erwarten, es sei denn, der ursprüngliche Code war sehr ineffizient. Bestimmte zeitaufwändige Vorgänge sollten jedoch bei der Optimierung priorisiert werden, insbesondere Eingabe-Ausgabe-Vorgänge.


Unabhängig davon, ob Sie mit Dateien arbeiten oder mit einer Datenbank interagieren, ist die Ausführungszeit für diese Aufgaben im Vergleich zu In-Memory-Vorgängen immer beachtlich. Sie können den Vorgang des Auslesens von Daten aus einer Datei nicht wesentlich beeinflussen, die Arbeit mit der Datenbank unterliegt jedoch Ihrer direkten Kontrolle. Als Entwickler verfügen Sie über alle Möglichkeiten, diese Interaktion deutlich zu verbessern.


Sehen wir uns die folgenden Strategien an, um die Arbeit mit Ihrer Datenbank effizienter zu gestalten und dadurch die Leistung Ihres Backend-Dienstes deutlich zu steigern


Abfragen optimieren

Heutzutage ist es selten, einen Backend-Webdienst zu finden, der kein ORM-System (Object-Relational Mapping) für Datenbankinteraktionen verwendet. Wenn Sie erstklassige Ergebnisse anstreben, sollten Sie eine Anpassung des ORM in Betracht ziehen. Obwohl ORMs effizient und fehlerfrei sind, sind sie für den allgemeinen Gebrauch konzipiert. Diese breite Anwendbarkeit geht oft auf Kosten einer hohen Leistung.


Denken Sie daran, dass ORMs so erstellt werden, dass sie mit verschiedenen Datenbanken kompatibel sind. Dies kann dazu führen, dass bestimmte Vorteile der Datenbank, die Sie für Ihr Projekt ausgewählt haben, nicht genutzt werden. Wie hier dargestellt, kann die Nutzung einzigartiger Datenbankfunktionen beispielsweise die Geschwindigkeit von Datenbankinteraktionen um das bis zu 30-fache steigern.


Anstatt sich ausschließlich auf die von einem ORM bereitgestellten Standardabfragen zu verlassen, lohnt es sich, eigene optimierte Abfragen zu erstellen. Benutzerdefinierte Abfragen erzielen häufig eine bessere Leistung, insbesondere in Szenarios mit mehreren Verknüpfungen.


Unten finden Sie ein einfaches Beispiel in Spring JPA, wie Sie die Leistung mithilfe einer Join-Abfrage verbessern können:

 @Transactional @Lock(LockModeType.PESSIMISTIC_READ) @Query(value = """ SELECT e FROM EmployeeRecord e LEFT JOIN DepartmentRecord d ON e.departmentId = d.id WHERE e.departmentId = :departmentId; """) List<EmployeeRecord> findEmployeesByDepartmentId(Integer departmentId);


Verwenden Sie flache Klassen

Die Verwendung komplexer Klassen mit verschachtelten Objekten und einem tief hierarchischen System kann zu einem erheblichen Verlust der Systemleistung führen. Oft ist es nicht erforderlich, die Datenbank nach der gesamten verschachtelten Struktur abzufragen, insbesondere wenn nicht alle Klassen in der Struktur vollständig genutzt werden.


Während eine verzögerte Initialisierung dazu beiträgt, unnötige Abfragen zu verschachtelten Objekten zu reduzieren, entstehen Herausforderungen, wenn ein verschachteltes Objekt benötigt wird, aber nicht alle seine Daten erforderlich sind. Die Lösung für dieses Dilemma besteht darin, flache Datenklassen zu verwenden.


Sie sollten eine Klasse erstellen, die darauf ausgelegt ist, nur die erforderlichen Felddaten aus der Datenbank zu sammeln. Wählen Sie dann mit einer benutzerdefinierten Datenbankabfrage, die alle erforderlichen Verknüpfungen enthält, nur die Felder aus, die wirklich benötigt werden.


Dieser Ansatz erhöht nicht nur die Abfragegeschwindigkeit, sondern reduziert auch den Datenverkehr von der Datenbank zu Ihrem Dienst.


Beispielsweise kann mit NamedParameterJdbcTemplate von Spring JPA eine flache Klasse mit den erforderlichen Feldern erstellt werden:

 public record EmployeeDepartment(Integer employeeId, String employeeName, String departmentName) { }


Als Nächstes werden mithilfe eines einfachen Skripts nur die erforderlichen Felder aus der Haupttabelle und den verknüpften Tabellen erfasst:

 public List<EmployeeDepartment> employeeDepartments() { return template.query(""" SELECT employees.employee_id, employees.employee_name, departments.department_name FROM employees LEFT JOIN departments ON employees.department_id = departments.department_id; """, new MapSqlParameterSource(), employeeDepartmentMapper); }


Dieser Ansatz wird die Belastung erheblich reduzieren und die Arbeit mit Daten deutlich effizienter machen.


Definieren Sie Hot Data

Der nächste wichtige Schritt bei der Arbeit mit Daten ist die Definition der Datentypen, wobei der Haupttyp Hot Data ist.


Hot Data sind die Daten, die der Dienst in Echtzeit verarbeitet. Diese Daten können nicht zwischengespeichert werden, da die Relevanz der Antwort des Webdienstes von seiner unmittelbaren Reaktionsfähigkeit abhängt. Daher müssen diese Daten immer aktuell sein. Der Dienst arbeitet kontinuierlich mit Hot Data, zeichnet kontinuierlich neue Werte auf und extrahiert Informationen für zeitnahe Aktualisierungen.


Um möglichst effizient mit Hot Data arbeiten zu können, ist es wichtig sicherzustellen, dass die Tabelle, in der sie gespeichert werden, möglichst kompakt bleibt.


  • Behalten Sie so wenig Spalten wie möglich bei

    Ihre Tabelle sollte nur die Felder enthalten, die aktiv verwendet werden, und alle anderen Daten in einer separaten Tabelle speichern, wobei nur die ID der relevanten Zeile erhalten bleibt. Mit diesem Ansatz können Sie bei Bedarf auf alle ungenutzten Felder zugreifen, beispielsweise für Berichtszwecke, ohne die Haupttabelle mit diesen Daten zu überlasten.


  • Halten Sie so wenig Reihen wie möglich

    Bewahren Sie keine Leitungen auf, die Sie nicht mehr benötigen. Verschieben Sie sie stattdessen in die Archivtabelle. Dieser Ansatz ermöglicht es Ihren Abfragen, die erforderlichen Zeilen schneller zu finden und gleichzeitig alle historischen Daten in einem Archiv beizubehalten. Durch die Automatisierung dieses Prozesses mit einem einfachen Job wird Ihr Aufwand für die Datenarchivierung minimiert.


  • Halten Sie die Indizes auf dem neuesten Stand

    Denken Sie daran, Indizes zu erstellen. Indizes sind für die schnelle Datensuche von entscheidender Bedeutung und werden von Programmierern oft übersehen. Eine ordnungsgemäße Indizierung kann die Suchzeiten und den Speicherverbrauch Ihrer Datenbank erheblich reduzieren. Stellen Sie sicher, dass Sie Indizes sowohl für Bedingungen als auch für Spalten erstellen, die an Verknüpfungen beteiligt sind, einschließlich zusammengesetzter Indizes.


  • Geben Sie die Verwendung von Fremdschlüsseln auf

    Durch die Verwendung von Fremdschlüsseln wird die Datenbank zusätzlich belastet, um sicherzustellen, dass der Schlüssel in der zugehörigen Tabelle vorhanden ist. Dadurch werden Datenvorgänge verlangsamt, insbesondere beim Schreiben von Daten. Verstehen Sie mich nicht falsch; Das Speichern eines Fremdschlüssels in einer solchen Tabelle ist möglich und manchmal sogar notwendig, aber es ist besser, den Schlüssel einfach als einfachen Wert zu speichern.


Mit diesen einfachen Methoden können Sie die Effizienz und den Nutzen Ihres Tisches maximieren.


Definieren Sie warme Daten

Warme Daten sind Daten, die zur Vorbereitung einer Antwort verwendet werden, deren Relevanz jedoch keine entscheidende Auswirkung hat. Beispiele hierfür sind Produktbeschreibungen oder eine Liste des verfügbaren Zubehörs. Beim Speichern solcher Daten ist eine genaue Überwachung der Tabellengröße nicht mehr erforderlich. Allerdings darf die Erstellung von Indizes für diese Tabellen nicht außer Acht gelassen werden, da diese häufig für Joins verwendet werden.


  • Warme Daten zwischenspeichern

    Ein wesentlicher Vorteil von Warm Data ist seine Cachefähigkeit. Sobald eine Anfrage gestellt wurde, können Sie die Daten im Speicher speichern, wodurch die Anzahl der Datenbankaufrufe reduziert und die Berechnungen beschleunigt werden. Bedenken Sie jedoch, dass der Cache regelmäßig aktualisiert werden muss.


  • Stellen Sie eine angemessene TTL (Time To Live) ein.

    Stellen Sie die richtige Time To Live (TTL) für einen ordnungsgemäßen Betrieb ein. Normalerweise reicht eine TTL von etwa 90 Sekunden aus, was der durchschnittlichen Zeit entspricht, die ein Benutzer benötigt, um auf einer Website eine Entscheidung zu treffen und eine Bestellung aufzugeben. Passen Sie die TTL immer an die Anforderungen Ihres Dienstes an.


  • Verwenden Sie kleinere Klassen, um warme Daten zu speichern

    Verwenden Sie zum Caching kompakte Klassen. Auch wenn vollständige Abfragen durchgeführt und alle Daten aus Tabellen erfasst werden, sollten Sie vermeiden, alles im Cache zu speichern. Speichern Sie nur die notwendigen Daten. Dieser Ansatz reduziert den Speicherverbrauch Ihres Backend-Dienstes erheblich.


Das Einrichten von Warm Data wird nicht viel Zeit in Anspruch nehmen und letztendlich werden Sie greifbare Ergebnisse erzielen.


Kalte Daten definieren

Kalte Daten beziehen sich auf Daten, die sich selten ändern, aber für eine Reaktion benötigt werden. Beispiele für solche Daten sind der Name oder die Adresse eines Geschäfts. Diese Daten ändern sich sehr selten und haben nur minimale Auswirkungen auf die Relevanz der Antwort.


  • Kalte Daten zwischenspeichern oder in einer Datei speichern

    Dieser Datentyp sollte immer zwischengespeichert werden. Wenn die Unterbringung solcher Daten im Speicher aufgrund ihrer Größe nicht möglich ist, sollten Sie erwägen, sie aus der Datenbank zu entladen und in Dateien in einem gebrauchsfertigen Format zu speichern. Wenn Sie es in Kategorien unterteilen und nur die am häufigsten verwendeten auswählen, können Sie den Speicherverbrauch reduzieren. Darüber hinaus verbessert dieser Ansatz die Geschwindigkeit deutlich im Vergleich zum Abrufen der Daten aus der Datenbank, da die Arbeit über das Netzwerk entfällt.


  • Cache bei Auslöser aktualisieren

    Die Lebensdauer (Time to Live, TTL) für einen solchen Cache ist normalerweise auf 24 Stunden festgelegt. Um den Cache auf dem neuesten Stand zu halten, sollten Sie eine Aufgabe planen oder einen Trigger erstellen, der Änderungen an diesen Daten überwacht und eine Cache-Aktualisierung initiiert. Wenn beispielsweise ein Endpunkt aufgerufen wird, Cold Data zu veröffentlichen oder zu aktualisieren, sollte ein Trigger aktiviert werden, um den Cache zu aktualisieren.


Die effektive Verwaltung kalter Daten ist auch ein wichtiger Teil der Optimierung der Reaktionseffizienz und steigert dadurch die Gesamtsystemleistung.


Abschluss

Zusammenfassend lässt sich sagen, dass die Optimierung des Backends eines Webservices nicht nur von der Code- und Algorithmusoptimierung abhängt. Die Verbesserung der Datenbankinteraktionen führt zu einer höheren Effizienz und Gesamtleistung des Dienstes. Durch die Implementierung von Techniken wie der Feinabstimmung von ORM-Abfragen (Object-Relational Mapping), der Verwendung flacher Datenklassen, der genauen Definition von Datentypen und der Einführung von Caching-Strategien kann die Serviceleistung erheblich gesteigert werden. Durch diese Maßnahmen wird der Webdienst letztendlich eine verbesserte Effizienz, Reaktionsfähigkeit und eine verbesserte Gesamtfunktionalität erreichen.


Wichtige Schritte :

  1. Optimieren Sie Datenbankabfragen und verlassen Sie sich nicht ausschließlich auf ORM-Implementierungen.
  2. Verwenden Sie flache Klassen, um die Speichernutzung zu reduzieren und die Antwortgeschwindigkeit zu erhöhen.
  3. Definieren Sie Datentypen, indem Sie sie als „Heiß“, „Warm“ oder „Kalt“ kategorisieren.
  4. Wenden Sie spezifische Strategien an, die auf jeden definierten Datentyp zugeschnitten sind.