Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
PostgreSQL
Seit PostgreSQL 9.0 (2010) gibt es eine eingebaute Replikation (Streaming Replication: PostgreSQL WAL-Shipping).
- http://www.postgresql.de/postgresql_outline.html → Überblick über die Eigenschaften
- http://www.postgresql.de/features.html → Überblick über die Funktionen
-
-
Anleitungen bzw. Beispiele
passwortloser login mit ~/.pgpass:
> touch ~/.pgpass > chmod 0600 ~/.pgpass > vi ~/.pgpass hostname:port:database:username:password > vi ~/.bashrc PGPASSFILE="$HOME/.pgpass" > echo "\dt;" | psql database
individuelle Konfiguration mit ~/.psqlrc:
> echo "\dt;" | psql postgresql://username:password@address:5432/database
> echo '\timing on' >> ~/.psqlrc > echo '\c postgresql://username@address:5432/database' >> ~/.psqlrc
PG-User ändert sein eigenes Passwort:
> psql -U dbuser -d dbname dbname=> \password Enter new password for user "dbuser": Enter it again: dbname=> quit
SHOW USERS:
> echo "\du" | psql -U postgres -d postgres
SHOW DATABASES:
> psql -U postgres -l > echo -e "\l" | psql -U mmroot -d postgres
SHOW TABLES:
> echo "\dt" | psql -U username -d database > echo "SELECT * FROM pg_catalog.pg_tables;" | psql -U username -d database
SELECT FROM TABLE:
> echo "echo "SELECT COUNT(*) FROM tabellenname;" | psql -U username -d database
CREATE DATABASE:
> echo "CREATE DATABASE database OWNER = username;" | psql -U postgres
CREATE TABLE:
> echo "CREATE TABLE tabellenname (...);" | psql -U username -d database > echo "CREATE TABLE film (ID serial, verzeichnis varchar(1000), datei varchar(100), name varchar(100), type varchar(100), jahr integer, laufzeit integer, altersfreigabe integer, genre varchar(100), produzent varchar(100), regie varchar(100), schauspieler varchar(10000), handlung varchar(100000), PRIMARY KEY (ID));" | psql -U username -d database
Tabellenstruktur anzeigen:
> echo "\d+ tabellenname" | psql -U username -d database
soll die ~/.psqlrc nicht berücksichtigt werden, dann braucht man -X
> echo "SELECT COUNT(*) FROM tabellenname;" | psql -X -U username -d database
SHOW CREATE TABLE:
> pg_dump --schema-only -U username -d database -t tabellenname
ADD PRIMARY KEY:
> ALTER TABLE tabellenname ADD PRIMARY KEY(spalte1, spalte2);
DROP TABLE:
> echo "DROP TABLE tabellenname;" | psql -U username -d database
SHOW CREATE TABLE:
> echo "SELECT * FROM pg_stat_activity;" | psql -U username
TEMP TABLE
DROP TABLE IF EXISTS TmpTabNamen; BEGIN TRANSACTION; CREATE TEMP TABLE TmpTabNamen AS SELECT ... FROM TabNamen WHERE ...; COMMIT; SELECT * FROM TmpTabNamen WHERE ...; DROP TABLE IF EXISTS TmpTabNamen;
PostgreSQL 12 auf Debian 11 installieren
Repository einrichten
> apt update && apt -y full-upgrade > wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc > /etc/apt/keyrings/pgdg.asc > apt -y install gnupg2 > echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list > apt update
den Postgresql-Client installieren
> apt install postgresql-client-12
den Postgresql-Server (incl. Client) installieren
> apt install postgresql-12
PostgreSQL-Wartung
Werkzeug für die PostgreSQL-Leistungsüberwachung, ähnlich top:
[root@freebsd12 ~]# cd /usr/ports/www/p5-LWP-UserAgent-WithCache && make clean && make && make install ; make clean
[root@freebsd12 ~]# cd /usr/ports/databases/pgtop && make clean && make && make install ; make clean
[root@freebsd12 ~]# touch ~/.pgtop
[root@freebsd12 ~]# chmod 0600 ~/.pgtop
[root@freebsd12 ~]# vi ~/.pgtop
user=postgres
pass=
host=localhost
port=5432
db=test
[root@erde ~]# su - postgres -c "echo 'CREATE DATABASE test OWNER = postgres;' | psql postgres"
CREATE DATABASE
[root@erde ~]# su - postgres -c "echo '\l' | psql postgres"
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
----------------+----------+----------+---------+-------------+-----------------------
...
test | postgres | UTF8 | C | de_DE.UTF-8 |
...
[root@freebsd12 ~]# pgtop
Manueller Aufruf für die DB-Wartung, gelöschte Bereiche wieder frei zugeben.
eine einzelne DB:
[root@freebsd12 ~]# su - postgres -c "echo 'vacuum verbose' | psql DatenbankName" ... ... ... VACUUM
alle DBs:
[root@freebsd12 ~]# su - postgres -c "vacuumdb -aefz"
SELECT pg_catalog.set_config('search_path', '', false)
SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;
SELECT pg_catalog.set_config('search_path', '', false)
vacuumdb: vacuuming database "postgres"
VACUUM (FULL, ANALYZE);
SELECT pg_catalog.set_config('search_path', '', false)
vacuumdb: vacuuming database "template1"
VACUUM (FULL, ANALYZE);
PostgreSQL-Datenbank bläht sich auf
Dealing with significant Postgres database bloat — what are your options?
Das Aktualisieren eines vorhandenen Datensatzes führt zu einem toten Tupel, der vorherigen Version des Datensatzes sowie einem neuen Datensatz. Wenn die Rate der erstellten toten Tupel die Fähigkeit der Datenbank überschreitet, tote Tupel automatisch zu bereinigen, tritt ein Aufblähen auf. Stellen wir uns ein Szenario vor, in dem eine Anwendung Datensätze mit durchschnittlich 1.000 Datensätzen pro Sekunde aktualisiert oder löscht und der Autovacuum-Daemon tote Tupel mit einer durchschnittlichen Rate von 800 pro Sekunde entfernt. Jede Sekunde treten 200 Tupel Blähungen auf. Beachten Sie, dass dies ein hypothetisches Szenario ist. Es ist nicht möglich, den Autovakuum-Daemon so einzustellen, dass tote Tupel mit 800/s entfernt werden.
Autovacuum-Daemon aktivieren:
> vi /etc/postgresql/10/main/postgresql.conf > cp /usr/local/share/postgresql/postgresql.conf.sample /usr/local/pgsql/data/postgresql.conf > vi /usr/local/pgsql/data/postgresql.conf ... track_counts = on ... autovacuum = on ...
erste Schritte in PostgreSQL
Übrigens! ChatGPT kann einem ruck-zuck die richtigen Befehle nennen und das auch noch wenn man die Frage in umgangssprachlichem Deutsch gestellt hat.
ein Backup einer Datenbank anlegen:
pg_dump -d filme -f postgres_backup_-_filme.sql
einen Benutzer "indy" anlegen:
createuser -U postgres --no-superuser --no-createdb --no-createrole indy echo "\du" | psql
einem DB-Benutzer Rechte über eine ganze DB erteilen:
echo "GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO indy;" | psql -d filme
einem DB-Benutzer Rechte über eine Tabelle erteilen:
echo "GRANT INSERT, UPDATE, DELETE ON TABLE tabellenname TO indy;" | psql -d filme
einen Benutzer löschen:
echo "DROP USER indy;" | psql
ein Datenbank-Backup in ein leeres DBMS einspielen:
echo "CREATE DATABASE filme;" | psql psql -d filme -f postgres_backup_-_filme.sql
alle Datenbanken anzeigen:
echo "\l" | psql
alle Tabellen aus einer Datenbank anzeigen:
echo "\dt" | psql database_name
Anzeigen der Struktur einer bestimmten Tabelle:
echo "\d table_name" | psql database_name
eine Tabelle löschen:
echo "DROP TABLE table_name;" | psql database_name
eine DB löschen:
echo "DROP DATABASE database_name;" | psql
Indexe anzeigen: \di Fremdschlüssel anzeigen: \dfk VIEWs anzeigen: \dv Funktionen anzeigen: \df
psql postgres -l echo "\l" | psql
echo "\dt" | psql -U indy -d filme
MySQL: SHOW FULL PROCESSLIST
SELECT * FROM pg_stat_activity;
1. Benutzer in PostgreSQL anlegen
zum PostgreSQL-root-User werden:
> su - postgres
User anlegen:
$ createuser fritz
wieder ausloggen und wieder "ich" werden:
$ exit
User anzeigen:
> echo "\dg" | psql postgres
Liste der Rollen
Rollenname | Attribute | Mitglied von
------------+-----------------------------------------------------------------+--------------
fritz | | {}
postgres | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}
2. Benutzer in PostgreSQL anlegen
zum PostgreSQL-root-User werden:
> su - postgres
Syntax anzeigen:
$ echo "\h CREATE USER;" | psql postgres
Anweisung: CREATE USER
Beschreibung: definiert eine neue Datenbankrolle
Syntax:
CREATE USER Name [ [ WITH ] Option [ ... ] ]
wobei Option Folgendes sein kann:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| CREATEUSER | NOCREATEUSER
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT Verbindungslimit
| [ ENCRYPTED | UNENCRYPTED ] PASSWORD 'Passwort'
| VALID UNTIL 'Zeit'
| IN ROLE Rollenname [, ...]
| IN GROUP Rollenname [, ...]
| ROLE Rollenname [, ...]
| ADMIN Rollenname [, ...]
| USER Rollenname [, ...]
| SYSID Uid
User anlegen:
$ echo "CREATE USER fritz;" | psql postgres $ echo "CREATE USER fritz WITH CREATEDB PASSWORD 'geheim';" | psql postgres
Passwort ändern:
$ echo "ALTER USER fritz WITH PASSWORD 'geheim';" | psql postgres
fritz alle Privilegien nehmen:
$ echo "REVOKE ALL ON ALL TABLES IN SCHEMA public FROM fritz;" | psql postgres
allen Usern alle Privilegien nehmen:
$ echo "REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC;" | psql postgres
User löschen
$ echo "DROP USER fritz;" | psql postgres
User anlegen:
$ echo "CREATE USER fritz WITH CREATEDB;" | psql postgres
wieder ausloggen und wieder "ich" werden:
$ exit
User anzeigen:
> echo "\dg" | psql postgres
Liste der Rollen
Rollenname | Attribute | Mitglied von
------------+-----------------------------------------------------------------+--------------
fritz | DB erzeugen | {}
postgres | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}
> echo "\du" | psql postgres
Liste der Rollen
Rollenname | Attribute | Mitglied von
------------+-----------------------------------------------------------------+--------------
fritz | DB erzeugen | {}
postgres | Superuser, Rolle erzeugen, DB erzeugen, Replikation, Bypass RLS | {}
> echo "ALTER USER fritz RESET tabellen_name;" | psql postgres > echo "GRANT UPDATE ON tabellen_name TO fritz;" | psql postgres > echo "REVOKE ALL PRIVILEGES ON tabellen_name FROM fritz;" | psql postgres > echo "REVOKE ALL PRIVILEGES ON tabellen_name FROM PUBLIC;" | psql postgres > echo "REVOKE ALL PRIVILEGES ON datenbank FROM fritz;" | psql postgres
PostgreSQL-Hilfe
Datenbanken auflisten:
> echo "\l" | psql postgres
Liste der Datenbanken
Name | Eigentümer | Kodierung | Sortierfolge | Zeichentyp | Zugriffsprivilegien
-----------+------------+-----------+--------------+-------------+-----------------------
postgres | postgres | UTF8 | C | de_DE.UTF-8 |
template0 | postgres | UTF8 | C | de_DE.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | C | de_DE.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(3 Zeilen)
Tabellen auflisten:
> echo "\dt" | psql postgres
Zugriffsprivilegien für Tabellen, Sichten und Sequenzen auflisten
> echo "\dp" | psql postgres
alle Konfigurationsparameter anzeigen:
> echo "SHOW ALL;" | psql postgres
Hilfe:
> psql --help > echo "\h" | psql postgres > echo "\?" | psql postgres ... Hilfe \? [commands] Hilfe über Backslash-Befehle anzeigen \? options Hilfe über psql-Kommandozeilenoptionen anzeigen \? variables Hilfe über besondere Variablen anzeigen \h [NAME] Syntaxhilfe über SQL-Anweisung, * für alle Anweisungen ...
Verbindungen anzeigen:
> echo "\conninfo" | psql postgres Sie sind verbunden mit der Datenbank "postgres" als Benutzer "fritz" via Socket in "/tmp" auf Port "5432".
Datenbank in PostgreSQL anlegen
Datenbank anlegen:
> createdb dbname
oder so
> echo "CREATE DATABASE dbname OWNER = fritz;" | psql postgres CREATE DATABASE
neue DB anzeigen:
> echo "\l" | psql postgres
Liste der Datenbanken
Name | Eigentümer | Kodierung | Sortierfolge | Zeichentyp | Zugriffsprivilegien
-----------+------------+-----------+--------------+-------------+---------------------
dbname | fritz | UTF8 | C | de_DE.UTF-8 |
postgres | pgsql | UTF8 | C | de_DE.UTF-8 |
template0 | pgsql | UTF8 | C | de_DE.UTF-8 | =c/pgsql +
| | | | | pgsql=CTc/pgsql
template1 | pgsql | UTF8 | C | de_DE.UTF-8 | =c/pgsql +
| | | | | pgsql=CTc/pgsql
(4 Zeilen)
Backup erstellen:
> pg_dump dbname > dbname.pgdump
Backup zurück spielen:
> cat dbname.pgdump | psql dbname
Tabelle in PostgreSQL anlegen
Tabelle anlegen:
> echo "CREATE TABLE film (ID serial, verzeichnis varchar(1000), datei varchar(100), name varchar(100), type varchar(100), jahr integer, laufzeit integer, altersfreigabe integer, genre varchar(100), produzent varchar(100), regie varchar(100), schauspieler varchar(10000), handlung varchar(100000), PRIMARY KEY (ID));" | psql dbname
Index (name_idx) in der Tabelle (film) auf eine Spalte (Name) angelegt:
> echo "CREATE INDEX name_idx ON film (name);" | psql dbname CREATE INDEX
Tabelle löschen:
> echo "DROP TABLE film;" | psql dbname DROP TABLE
mal reinschauen:
> echo "SELECT * FROM film;" | psql filme id | verzeichnis | datei | name | type | jahr | laufzeit | altersfreigabe | genre | produzent | regie | schauspieler | handlung ----+-------------+-------+------+------+------+----------+----------------+-------+-----------+-------+--------------+---------- (0 Zeilen)
Datensätze in der Tabelle
zwei Datensätze eintragen:
INSERT INTO film (verzeichnis, datei, name, type, jahr, laufzeit, altersfreigabe, genre, produzent, regie, schauspieler, handlung) VALUES ('/Filme/','Otto_der_Film.mp4','Otto der Film','Film',1985,5100,0,'Komödie','Horst Wendlandt','Xaver Schwarzenberger, Otto Waalkes','Otto Waalkes',''), ('/Filme/','Grosse_Pointe_Blank.mp4','Ein Mann - ein Mord','Film',1997,6420,16,'Komödie','Susan Arnold, Roger Birnbaum','George Armitage','John Cusack','');
beide Datensätze nacheinander ändern:
UPDATE [Tabellenname] SET [Spaltenname1]='Inhalt1', [Spaltenname2] = 'Inhalt2' WHERE [Spaltenname3] = 'Inhalt3'; UPDATE film SET genre='Filmkomödie', handlung = 'Otto wächst im beschaulichen Ostfriesland auf.' WHERE datei = 'Otto_der_Film.mp4'; UPDATE film SET genre='Filmkomödie', handlung = 'Martin Blank ist Profikiller. Nicht immer läuft alles nach Plan, weshalb seine Auftraggeber unzufrieden sind.' WHERE datei = 'Grosse_Pointe_Blank.mp4';
eine Tabelle umbenennen
ALTER TABLE [alter Tabellenname] RENAME TO [neuer Tabellenname];
eine Spalte zur Tabelle hinzufügen
https://oracleplsql.info/alter-table-postgresql.html
ALTER TABLE [Tabellenname] ADD [Spaltenname] [Spaltentyp]; ALTER TABLE order_details ADD sort_datum date;
Es gibt keine Möglichkeit, hier eine Anweisung mit zugeben, um die Spalte an einer bestimmten Stelle einzufügen!
eine neue Tabelle anlegen, die genau die gleichen Spalten hat wie eine bereits vorhandene
CREATE TABLE [neuer Tabellenname] (LIKE [alter Tabellenname]);
Volltextsuche (case-insensitive)
> echo "SELECT * FROM Tabelle WHERE Spalte ILIKE ('%suchzeichen%');" | psql -U Benutzer -d Datenbank
> echo "SELECT * FROM video WHERE dateiname ILIKE ('%otto%');" | psql -U mmroot -d mm_oeffentlich
weitere PostgreSQL-Kommandos
Verbindungen: echo "\conninfo" | psql postgres User anzeigen: echo "\dg" | psql postgres Zugriffsprivilegien: echo "\dp" | psql dbname Standard-Zugriffsprivilegien: echo "\ddp" | psql dbname Datentypen: echo "\dT" | psql dbname alle Datenbanken anzeigen: echo "\l" | psql postgres alle Relationen (Tabellen+Indizes+...): echo "\d" | psql dbname Tabellen: echo "\dt" | psql dbname Tablespaces: echo "\db" | psql dbname Indizes: echo "\ds" | psql dbname Schemas: echo "\dn" | psql dbname Trigger: echo "\dy" | psql dbname Domänen: echo "\dD" | psql dbname Funktionen: echo "\df" | psql dbname Objektbeschreibungen: echo "\dd" | psql dbname Large Objects: echo "\dl" | psql dbname Operatoren: echo "\do" | psql dbname installierten Erweiterungen: echo "\dx" | psql dbname Aggregatfunktionen: echo "\da" | psql dbname Konversionen: echo "\dc" | psql dbname Textsuchekonfigurationen: echo "\dF" | psql dbname Textsuchewörterbücher: echo "\dFd" | psql dbname Textsucheparser: echo "\dFp" | psql dbname Textsuchevorlagen: echo "\dFt" | psql dbname Liste der prozeduralen Sprachen: echo "\dL" | psql dbname Liste der Operatoren: echo "\do" | psql dbname Liste der Sortierfolgen: echo "\dO" | psql dbname Stringausgabe: echo "\echo" | psql dbname Zeichensatzkodierung: echo "\encoding" | psql dbname Zeldtrennzeichen: echo "\f ' '" | psql dbname Ausgabe direkt in eine Datei: echo "\o '/tmp/datenbankausgabe.txt'" | psql dbname Ausgabe in eine Datei: echo "\w '/tmp/datenbankausgabe.txt'" | psql dbname Ausgabe einem Kommando übergeben: echo "\w '| /bin/systembefehl'" | psql dbname
SQL
UNION und UNION DISTINCT entfernen alle doppelten Zeilen, UNION ALL gibt dagegen auch die doppelten Zeilen aus, um schneller zu sein.
(SELECT * FROM tabelle1) UNION (SELECT * FROM tabelle2)
INTERSECT zeigt alle Zeilen, die in beiden Ausgaben vorhanden sind, doppelten Zeilen werden entfernt, INTERSECT ALL gibt dagegen auch die doppelten Zeilen aus, um schneller zu sein.
(SELECT * FROM tabelle1) INTERSECT (SELECT * FROM tabelle2)
EXCEPT gibt alle Zeilen zurück, die im Ergebnis von SELECT * FROM tabelle1, aber nicht im Ergebnis von SELECT * FROM tabelle2 enthalten sind. (Dies wird manchmal als Unterschied zwischen zwei Abfragen bezeichnet.) Auch hier werden Duplikate entfernt, sofern nicht EXCEPT ALL verwendet wird.
(SELECT * FROM tabelle1) EXCEPT (SELECT * FROM tabelle2)
Damit die Gegenüberstellung der beiden Ausgaben funktioniert, müssen beide Ausgaben die gleiche Anzahl an Zeilen haben und vom gleichen Datentyp sein.
Mehrfacheinträge in einer Tabelle finden
- mehrfache.sql
DROP TABLE mehrfach_vorhanden; CREATE TABLE mehrfach_vorhanden ( anzahl INT, zeile VARCHAR(10000) ); DO $$ DECLARE eine_zeile VARCHAR(10000); BEGIN FOR eine_zeile IN SELECT name FROM liste GROUP BY 1 LOOP INSERT INTO mehrfach_vorhanden SELECT COUNT(name), eine_zeile FROM kino WHERE name = eine_zeile; END LOOP; END; $$ LANGUAGE PLPGSQL; DELETE FROM mehrfach_vorhanden WHERE ANZAHL = 1; SELECT anzahl, zeile FROM mehrfach_vorhanden ORDER BY 1 ASC;
Am Ende werden in der zweiten Spalte alle mehrfach vorhandenen Einträge (Namen) und in der ersten Spalte die Anzahl dieser Einträge ausgegeben:
cat mehrfache.sql | psql -h 192.168.0.100 -p 5432 -U dbnutzer datenbank
Summierung von Spesenabrechnungen
So können beispielsweise die Gesamtausgaben (Spesen) jeder (mehrfach) eingetragenen Person leicht berechnet werden:
echo "SELECT SUM(ausgaben), name FROM spesen GROUP BY 2 ORDER BY 1 ASC;" | psql -h 192.168.0.100 -p 5432 -U buchhaltung db2019
PostgreSQL-Replikation (Cluster)
PostgreSQL-Replikation: Ein Statusbericht - 04/2017
-
- Citus: https://www.citusdata.com/
- PostgreSQL Cluster Guide 101: Easy Set-Up and How to Deploy for High Availability - Sharon Rithika • February 25th, 2022
PgPool
FreeBSD: > pkg install databases/pgpool-II-42
Debian: > apt install pgpool2
