MAISON CODE .
/ Tech · Database · SQL · Postgres · Scaling

Datenbankskalierung: Den Engpass vermeiden

Die Datenbank ist immer der Single Point of Failure bei der Skalierung. Strategien für Postgres-Optimierung, Read Replicas und Sharding.

AB
Alex B.
Datenbankskalierung: Den Engpass vermeiden

Das schwächste Glied des Monolithen

Sie können Ihre Frontend-Server stufenlos skalieren (fügen Sie einfach weitere Knoten hinter dem Load Balancer hinzu). Sie können Ihre API-Server stufenlos skalieren (Serverlose Funktionen). Sie können Ihre Primärdatenbank nicht einfach skalieren. Es gibt (normalerweise) nur eine Quelle der Wahrheit. Eine Festplatte. Ein Masterprozess. Wenn der Datenverkehr ansteigt, erreicht die CPU 100 % und die Abfragelatenz steigt von 10 ms auf 10.000 ms. Die Seite stirbt. Die Skalierung der Datenbank ist das schwierigste Problem im Backend-Engineering.

Warum Maison Code dies bespricht

Bei Maison Code sehen wir, dass gültige Startups aufgrund von SQL sterben. Sie schreiben Code wie „SELECT * FROM Orders“. Bei 100 Bestellungen funktioniert es einwandfrei. Bei 1.000.000 Bestellungen stürzt der Server ab. Wir optimieren Datenbanken für Hohe Kardinalität und Hohen Durchsatz. Wir wissen, dass das „Hinzufügen von Indizes“ nicht ausreicht. Sie benötigen Architekturänderungen (Caching, Replikation, Partitionierung).

Strategie 1: Indexierung (Die niedrig hängende Frucht)

Die meisten Leistungsprobleme sind fehlende Indizes. Szenario: Suche nach einem Benutzer per E-Mail. Abfrage: „SELECT * FROM users WHERE email = ‚alex@example.com‘“. Ohne Index: Die Datenbank scannt 1.000.000 Zeilen (sequentieller Scan). AN). Mit Index (B-Tree): Die DB springt direkt zur E-Mail. O(log N). Kosten: Indizes verlangsamen Schreibvorgänge (INSERT/UPDATE), da der Indexbaum aktualisiert werden muss. Regel: Indexspalten, die in „WHERE“, „JOIN“ und „ORDER BY“ verwendet werden.

Strategie 2: Caching (Redis)

Die schnellste Abfrage ist die, die Sie nicht stellen. SQL ist langsam (Festplatten-E/A, CPU-Berechnung). Redis ist schnell (In-Memory, Schlüsselwert). Muster: Look-Aside-Cache. „Javascript asynchrone Funktion getProduct(id) { // 1. Cache prüfen const zwischengespeichert = waiting redis.get(product:€{id}); if (cached) return JSON.parse(cached);

// 2. DB abfragen (langsam) const product = waiting db.query(‘SELECT * FROM products WHERE id = ?’, [id]);

// 3. Im Cache speichern (TTL 5 Min.) wait redis.set(product:€{id}, JSON.stringify(product), ‘EX’, 300);

Produkt zurücksenden; } „ Dadurch werden 90 % des Leseverkehrs von der Datenbank entlastet.

Strategie 3: Replikate lesen

Selbst mit Caching können Lesevorgänge die CPU überlasten. Lösung: Erstellen Sie Kopien der Datenbank (Replikate).

  • Primärknoten: Verarbeitet Schreibvorgänge (INSERT, UPDATE, DELETE). Synchronisiert Änderungen mit Replikaten (asynchron).
  • Replikatknoten: Handle-Lesevorgänge (SELECT). Kompromiss: Replikationsverzögerung. Der Benutzer aktualisiert sein Profil. Sie aktualisieren die Seite sofort. Sie sind auf ein Replikat gestoßen, das das Update noch nicht erhalten hat. Sie sehen das alte Profil. Fix: „Lesen Sie Ihre eigenen Schreibvorgänge“. Erzwingen Sie für den aktuellen Benutzer das Lesen von der Primärseite. Für öffentliche Daten lesen Sie aus dem Replikat.

Strategie 4: Verbindungspooling (PgBouncer)

Postgres hat ein Limit für gleichzeitige Verbindungen (z. B. 100 beibehalten). Serverlose Funktionen (Lambda) erzeugen 1.000 Instanzen. Wenn 1.000 Instanzen versuchen, eine Verbindung zu öffnen, stürzt Postgres ab. Lösung: Ein Proxy (PgBouncer / Supabase Pooler). Der Proxy hält 100 offene Verbindungen zur Datenbank. Die 1.000 Lambdas sprechen mit dem Proxy. Der Proxy stellt die Abfragen in die Warteschlange und führt sie über die 100 Verbindungen aus. Dies ist für serverlose Architekturen obligatorisch.

Strategie 5: Vertikale Partitionierung (Tabellen aufteilen)

Die Tabelle „Benutzer“ enthält „bio“ (Text, groß) und „last_login“ (Datum, klein). Wenn Sie häufig „last_login“ abfragen, „bio“ die Zeilengröße jedoch sehr groß macht, liest die Datenbank zu viele Daten von der Festplatte. Teile es auf: Tabelle „User_Core“ (ID, E-Mail, Passwort, last_login). Tabelle „User_Profile“ (ID, Bio, Avatar). Jetzt geht „SELECT last_login FROM User_Core“ rasend schnell, da mehr Zeilen in RAM-Seiten passen.

6. Materialisierte Ansichten: Den Erfolg vorab berechnen

„Zeigen Sie mir den Gesamtumsatz für 2024.“ SELECT SUM(amount) FROMorders WHERE year = 2024. Dadurch werden 10 Millionen Zeilen gescannt. Es dauert 5 Sekunden. Lösung: Materialisierte Ansicht. „ERSTELLEN SIE MATERIALIZED VIEW annual_revenue AS SELECT …“. Postgres berechnet das Ergebnis und speichert es als physische Tabelle auf der Festplatte. Die Abfrage dauert 1 ms. Kompromiss: Die Daten sind veraltet. Sie müssen „MATERIALIZED VIEW“ regelmäßig aktualisieren (z. B. jede Stunde). Perfekt für Dashboards, bei denen „Echtzeit“ nicht unbedingt erforderlich ist.

7. Automatische Datenbankskalierung (Serverless Aurora)

Was ist, wenn Sie keine Replikate verwalten möchten? Amazon Aurora Serverless v2. Es fügt automatisch CPU/RAM hinzu, wenn der Datenverkehr ansteigt, und schrumpft, wenn der Datenverkehr sinkt. Die Skalierung erfolgt in Bruchschritten (ACUs). Es bietet Ihnen effektiv das „Infinite Scaling“-Versprechen von NoSQL, jedoch mit vollständiger SQL-Kompatibilität. Es ist teuer, aber günstiger als die Beauftragung eines DBA mit der manuellen Bereitstellung von Lesereplikaten um 3 Uhr morgens.

9. Zeitreihendaten (TimescaleDB)

„Jeden Seitenaufruf protokollieren.“ „Protokollieren Sie jeden Thermometerwert.“ Standard-Postgres erstickt beim Einfügen von 10.000 Zeilen/Sekunde in eine einzelne Tabelle. Indizes werden fragmentiert. Lösung: TimescaleDB (Postgres-Erweiterung). Es partitioniert Daten automatisch nach Zeit („Hypertables“). „Bestellungen_2024_01“, „Bestellungen_2024_02“. Sie fragen es als eine Tabelle „Bestellungen“ ab, aber physisch handelt es sich um kleine Teile. Das Löschen alter Daten erfolgt sofort („DROP TABLEorders_2020“). „LÖSCHEN AUS Bestellungen, WO Jahr=2020“ dauert Stunden.

10. Erweiterte Partitionierungsstrategien

Durch die vertikale Partitionierung werden Spalten geteilt. Horizontale Partitionierung teilt Zeilen. Nach Region: „users_eu“, „users_us“. Dies hilft bei der DSGVO (Data Residency). „Europäische Daten verlassen niemals den EU-Server.“ Die deklarative Partitionierung von Postgres macht dies beherrschbar. So skalieren wir SaaS-Apps für Millionen von Mietern, ohne einen Mainframe kaufen zu müssen.

11. Die Sicht des Skeptikers

„Verwenden Sie einfach DynamoDB / NoSQL. Es skaliert unbegrenzt.“ Gegenpunkt: NoSQL skaliert Schreibvorgänge, schlägt jedoch bei Relationalen Daten fehl. „Zeige mir alle Bestellungen von Benutzern in Paris, die rote Schuhe gekauft haben.“ In SQL: Eine Abfrage. In NoSQL: Ein Albtraum anwendungsseitiger Verknüpfungen und mehrfacher Abrufe. Die meisten E-Commerce-Daten sind relational. Bleiben Sie bei SQL (Postgres), bis Sie die Google-Skala erreichen.

FAQ

F: Wann sollte Sharding verwendet werden? A: Fast nie. Sharding (das Aufteilen von Daten auf mehrere Server basierend auf der Benutzer-ID) ist äußerst komplex. Sie verlieren ACID-Transaktionen über Shards hinweg. Führen Sie kein Sharding durch, bis Sie über mehr als 10 TB Daten verfügen. Die vertikale Skalierung (größerer Server) funktioniert bis zu diesem Zeitpunkt überraschend gut.

F: ORM vs. Raw SQL? A: Prisma/Drizzle (ORM) für Produktivität. Roh-SQL für komplexe Berichte oder hochoptimierte Abfragen. Moderne ORMs sind für 99 % der Abfragen gut genug.

Fazit

Die Datenbank ist das Herzstück Ihres Stacks. Wenn es aufhört zu schlagen, stirbt die App. Behandle es mit Respekt. Indizieren Sie Ihre Fremdschlüssel. Cachen Sie Ihre Hot-Pfade. Und führen Sie niemals „DROP TABLE“ am Freitag aus.

Datenbank erstickt?

Wenn bei Ihren Abfragen eine Zeitüberschreitung auftritt oder Ihre CPU ein Redlining durchführt, kann Maison Code Ihr Schema optimieren. Wir analysieren Abfragepläne, implementieren Caching-Strategien und erstellen Replikatsätze.

Kontaktieren Sie uns, um Ihre Daten zu skalieren.



Abfragen zu langsam?

Wir optimieren die Datenbankarchitektur mithilfe von Indizierung, Caching und Read Replicas, um große Skalierungen zu bewältigen. Stellen Sie unsere Architekten ein.