NoSQL mit PostgreSQL pgconf.de – November 2015 Hannu Krosing Harald Armin Massa Agenda ● Wer sind 2ndQuadrant, Hannu, Harald (2min) ● Begriffsbestimmung: NoSQL ● Warum NoSQL? ● Postrelationales PostgreSQL: Not Only SQL 2ndQuadrant Beiträge zu ● ● Core PostgreSQL (Beispiele) – PITR – Hot Standby – Synchronous Replication – CREATE EXTENSION – BDR / UDR Ecosystem (Beispiele) – pgbarman – repmgr Wer ist 2ndQuadrant? ● PostgreSQL Support Company – 24/7 PostgreSQL Produktiv Support – Wir finden in vereinbarter Zeit Lösungen für Bugs, die den PostgreSQL Betrieb stören. Gegen Geld. ● Remote DBA ● Platin Sponsor PostgreSQL Projekt ● Dienstleistungen, PostgreSQL Support zu ermöglichen – Entwicklung – Consulting / Training Hannu ● DBA und Database Architect bei Skype – ● ● ● Betreuung Wachstum 1 nach 100en von Servern Co-Author des Buches "PostgreSQL 9 Administration Cookbook" zusammen mit Simon Riggs. Code & Bugfixes & Designbeiträge PostgreSQL Spezialisiert auf Skalierung, Python um und in PostgreSQL Harald ● ● PostgreSQL Nutzer seit 1996 Unternehmer, Python-Anwendungen mit PostgreSQL (+andere DB) ● Mitorganisator europäische PostgreSQL Konferenz ● Pilotanwender PostgreSQL unter Windows ● Seit 2010 2ndQuadrant Partner, Geschäftsführender Gesellschafter 2ndQuadrant Deutschland GmbH NoSQL - Begriffsbestimmung ● ● Initiiert als „Not Only SQL“ = „nicht nur SQL“ Speichern und Lesen von Daten in anderen Modellen als Tabellen / Relationen – ● Eigentlich „NoREL“ Aufbegehren gegen SQL Warum nicht relational? Herausforderungen Relationale DB 1 ● ● ● Struktur sehr weit weg von Relationen – Verträge – Webseiten „gefühlter“ Overhead von SQL – Parser / Executor – kognitive Last weitere Sprache – kognitive Last descriptive Sprache / Kontrollverlust Serialisierungs-Overhead Objekt → Relation Herausforderungen Relationale DB 2 ● Datenschema – Transaktionales DDL selten außerhalb – Organisatorisches Hemmen von Änderungen ● Applikationskompatibilität? – Schemaänderungen bei logischen Replikationen herausfordernd – ALTER TABLE ● Reduce lock levels of CREATE TRIGGER and some ALTER TABLE, CREATE RULE actions. (Simon, 28. July 2010) Herausforderungen Relationale DB 3 ● ● Anforderungen verteilte Datenbanken (WebScale) – CAP (Konsistent, Verfügbar, Paritionstolerant consistent, available, partition tolerance) – Konsistenz dauert länger Service Oriented Architecture – Programmkommunikation über Service-APIs – Relative einfache Abfragen – Service-Middleware verantwortet Datenkonsistenz NoSQL Varianten ● ● Column Oriented Stores Key-Value Datenbanken / Stores (z.b. REDIS, Memcache, Btrieve) ● Document Databases (CouchDB, MongoDB) ● GraphDatabases "GraphDatabase PropertyGraph" by Originally uploaded by Ahzf (Transferred by Obersachse) Licensed under CC0 via Wikimedia Commons - Warum dennoch PostgreSQL ● ● ● ACID wird gebraucht Langlebigkeit / Fehlertoleranz mit bewährten PostgrSQL Techniken – Disaster Recovery / PITR (pg_barman) – Hochverfügbarkeit Kombination teilstrukturierte Daten mit relationalen Informationen – z.B. Dokumente mit organisatorischer Einbindung ● Nutzung weltbestes Supportangebot ● Because you can. Gründe, warum das möglich ist ● PostgreSQL = PostRelational ● Erweiterbarkeit PostgreSQL ● ● NoSQL als Hack – PostgreSQL die Hackers Database PostgreSQL sehr verlässlich – Verlässlichkeit dauert; tuning nach schneller als Dokument Datenbank ● Unstrukturierte Daten in PostgreSQL „einfach“ möglich seit 2003 Teodor Sigaev, Oleg Bartunov, Alexander Korotkov hstore ● ● ● Id, Col1, col2, col3, col4…. – Viele Datenspalten – Nur nach wenigen wird gesucht, andere einzig Ausgabe Speichert Key/Value Paare (inspiriert durch Perl Hashes) Binäres Speicherformat hstore – Vor- und Nachteile ● Flexible Speicherung Semi-strukturierter Daten ● Reichhaltige Operatoren vorhanden ● Kompakte Speicherung Binärformat ● ● ● Keine Baumstrukturen (wie in JSON verfügbar, JSON existiert seit ~2006) Abbildung in Programmiersprachen? Standard für JSON: (ECMA-404 The JSON Data Interchange Standard, JSON RFC-7159) Standard für hstore? JSON JSON in PostgreSQL ● ● ● Vor PostgreSQL 9.2: Speichern in TEXT Spalten, zugriff per PL/PERL, PL/PYTHON, PL/V8… PostgreSQL 9.2: JSON Datentyp; Speicherung als Text, Validierung, Zugriffsoperatoren PostgreSQL 9.4: JSONB – November 2013: Binäres Speicherformat gemeinsam für hstore und jsonb – Januar 2014: binäres Speicherformat in PostgreSQL Core jsonb CREATE TABLE BUECHER ( Titel citext not null, isbn isbn not null primary key, publikationsinfo jsonb not null ) CREATE INDEX ON buecher USING GIN (publikationsinfo); → Alle Operationen CREATE INDEX ON buecher USING GIN (publikationsinfo json_path_ops); → nur search path operator "@>", kleinerer Index SELECT count(*) FROM buecher WHERE publikationsinfo @> '{ "Verlag" : "2ndQuadrant Verlag" }'; Wie schnell? ● Benchmarks von Oleg / Teodor / Alexander – MacBookAir, 8GB RAM, 256 GB SSD ● 1'252'973 Delicious Lesezeichen ● Ladezeiten – TEXT: 34 s – ohne Validierung – JSON: 37 s - json Validierung – Jsonb: 43 s - json Validierung, Binäre Speicherung (MongoDB 2.6.0: ~13 Minuten für Load) Suche in JSON-Data CREATE INDEX gin_jb_path_idx ON jb USING gin(jb jsonb_path_ops); EXPLAIN ANALYZE SELECT count(*) FROM jb WHERE jb @> '{"tags": [{"term":"NYC"}]}'::jsonb; QUERY PLAN --------------------------------------------------------------------------------------Aggregate (cost=4732.72..4732.73 rows=1 width=0) (actual time=0.644..0.644 rows=1 loops=1) -> Bitmap Heap Scan on jb (cost=33.71..4729.59 rows=1253 width=0) (actual time=0.102..0.620 rows=285 loops=1) Recheck Cond: (jb @> '{"tags": [{"term": "NYC"}]}'::jsonb) Heap Blocks: exact=285 -> Bitmap Index Scan on gin_jb_path_idx (cost=0.00..33.40 rows=1253 width=0) (actual time=0.062..0.062 rows=285 loops=1) Index Cond: (jb @> '{"tags": [{"term": "NYC"}]}'::jsonb) Planning time: 0.056 ms Execution runtime: 0.668 ms Suche – hier und anderswo ● Operator contains, aka @> in PostgreSQL – Json: 10s, seqscan – Jsonb: 8.5ms, GIN JSONB_OPS – Jsonb: 0.7ms, GIN JSONB_PATH_OPS – Mongo: 1.0ms btree index Mögliche Anwendung ● Daten mit häufigen Strukturänderungen in JSONb feld speichern ● indizieren per GIN ● evtl. funktionale Indizes auf Inhalte einzelner Felder ● ● ● wenn sich Datenmodell stabilisiert, keys / Values aus JSON Objekten nach Spalten migrieren kann über Update / Insert Trigger Applikations-Transparent erfolgen Daten in Spalten dann in kompletter relationaler Reportbarkeit Teil 2: Geschwindigkeit ● Mehr im Speicher halten ● Verlässlichkeit reduzieren ● Schreiben reduzieren ● Scaling auf multiple Maschinen PostgreSQL als in-Memory-DB ● ● ● Festplatten und Speicherformat identisch Persistenz ist durch WAL entkoppelt, kann ausgeschaltet werden Prozess-Modell mit gemeinsamen Daten + Speicherbereichen per Backend ● „gut genug“ für viele Anwendungen ● „darf's ein Terabyte mehr sein“ Verlässlichkeit reduzieren ● Daten werden verloren gehen ● Es ist einzig unsicher, wann nur verwenden, wenn Daten nicht erhalten bleiben müssen Was macht so verlässlich? 1340 in Genua erfunden Was macht so verlässlich? WALrecords 1340 in Genua erfunden table files Verlässlichkeit reduzieren (0) ● ● UNLOGGED TABLES Seit PostgreSQL 9.1 verfügbar CREATE UNLOGGED TABLE GRBILANZ (soll NUMERIC(40), haben NUMERIC(2)); ● Kein WAL wird geschrieben ● Messungen: 13-17% mehr TPS gemäßt pg_bench → PITR, Disaster Recovery, Streaming Replication sind nicht mehr möglich Verlässlichkeit reduzieren ● Nur bei Daten, die verlorengehen dürfen, Beispiele – Load OpenGeo Daten – Initialladen Datenbank aus DUMP NACH LOAD WIEDER VERLÄSSLICH MACHEN – Datawarehouses, beschickt aus anderen Systemen – Sessionstores bei Webservern Verlässlichkeit reduzieren (1) ● WAL_LEVEL = minimal ● Weniger WAL Schreiblast ● Crash Recovery bleibt möglich ● ● PITR; Streaming Replication; disaster Recovery entfallen Sowieso Default Einstellung :( Verlässlichkeit reduzieren (2) ● ● ● ● ● SYNCHRONOUS_COMMIT = off Kein Warten auf geschriebenes WAL, bevor COMMIT als erfolgreich gemeldet ist Keine Datenkorruption Transaktionen, die als „geschrieben“ gemeldet waren, können verloren gehen Transaktionen gehen konsistent verloren Bewußt einsetzen! In Beratung durch Datenbank Experten investieren Verlässlichkeit reduzieren (3) ● ● ● FULL_PAGE_WRITES = OFF Nach Checkpoint, erstes WAL-Schreiben nicht mehr zwingend ganze Seite→ weniger Schreiblast Systemcrash wird zur Datenkorruption führen Recovery kann scheitern Einzig für „verlierbare Situationen“ Verwenden. z.B. initialload von Datenbank Dumps. Nicht im Regelbetrieb verwenden Verlässlichkeit reduzieren (4) ● ● FSYNC = OFF Bestätigung des Schreibens auf Festplatte wird nicht abgewartet ● Datenkorruption wird passieren ● Sehr schnell Verwenden für: - initialload von Datenbanken - einlesen von Geodaten - Datenabzug „nur schauen“ auf Extranet-Server NACH LOAD für Betrieb wieder einschalten! Einschalten prüfen: postgres=# show fsync; fsync ------on Weniger Schreiblast multiple Server ● ● Umstellen Trigger Based Replikation (Slony, Bucardo, Londiste) nach Streaming Replication / UDR pg_logical (BDR). Trigger basiert: – Trigger auf DML (insert, update..) – Speicherung in Queue-Tabelle – Daten in Haupttabelle+WAL, Daten in Queue+WAL – Kosten für Encoding – Kosten für Queue Maintainance Schreiben Reduzieren, multiple Server Leseskalierung ● Daten werden von Applikation auf 1x PostgreSQL geschrieben ● PostgreSQL repliziert an viele Slaves ● Lesezugriffe erfolgen auf Slaves verteilt Leseskalierung Schreibzugriffe Applikation Replikation Lesende Zugriffe Applikation Leseskalierung pg_bouncer Anwendung Replik ation Ende