Da Postgres viel vernünftiger ist als MySQL, gibt es nicht so viele "Tricks", über die man berichten kann ;-)
Das Handbuch enthält einige nützliche Tipps zur Leistung .
Einige andere leistungsbezogene Dinge, die Sie beachten sollten:
- Stellen Sie sicher, dass das Autovakuum eingeschaltet ist
- Stellen Sie sicher, dass Sie Ihre postgres.conf durchgesehen haben (effektive Cache-Größe, freigegebene Puffer, Arbeitsmem ... viele Optionen zum Optimieren).
- Verwenden Sie pgpool oder pgbouncer , um Ihre "echten" Datenbankverbindungen auf ein Minimum zu beschränken
- Erfahren Sie, wie EXPLAIN und EXPLAIN ANALYZE funktionieren. Lernen Sie, die Ausgabe zu lesen.
- CLUSTER sortiert Daten auf der Festplatte nach einem Index. Kann die Leistung großer (meistens) schreibgeschützter Tabellen erheblich verbessern. Das Clustering ist eine einmalige Operation: Wenn die Tabelle anschließend aktualisiert wird, werden die Änderungen nicht geclustert.
Hier sind einige Dinge, die ich als nützlich empfunden habe und die per se nicht mit der Konfiguration oder Leistung zusammenhängen.
Um zu sehen, was gerade passiert:
select * from pg_stat_activity;
Suche verschiedene Funktionen:
select * from pg_proc WHERE proname ~* '^pg_.*'
Größe der Datenbank ermitteln:
select pg_database_size('postgres');
select pg_size_pretty(pg_database_size('postgres'));
Größe aller Datenbanken ermitteln:
select datname, pg_size_pretty(pg_database_size(datname)) as size
from pg_database;
Größe von Tabellen und Indizes ermitteln:
select pg_size_pretty(pg_relation_size('public.customer'));
Oder um alle Tabellen und Indizes aufzulisten (wahrscheinlich einfacher, dies anzuzeigen):
select schemaname, relname,
pg_size_pretty(pg_relation_size(schemaname || '.' || relname)) as size
from (select schemaname, relname, 'table' as type
from pg_stat_user_tables
union all
select schemaname, relname, 'index' as type
from pg_stat_user_indexes) x;
Oh, und Sie können Transaktionen verschachteln, Teiltransaktionen zurücksetzen ++
test=
BEGIN
test=
count
0
(1 row)
test=
INSERT 0 1
test=
SAVEPOINT
test=
UPDATE 3
test=
ROLLBACK
test=
COMMIT
test=
count
1
(1 row)
Der einfachste Trick, um postgresql viel leistungsfähiger zu machen (abgesehen von der Einstellung und Verwendung der richtigen Indizes natürlich), besteht darin, ihm mehr RAM zum Arbeiten zu geben (falls Sie dies noch nicht getan haben). Bei den meisten Standardinstallationen ist der Wert für shared_buffers (meiner Meinung nach) viel zu niedrig. Sie können einstellen
in postgresql.conf. Teilen Sie diese Zahl durch 128, um eine ungefähre Menge an Speicher (in MB) zu erhalten, die Postgres beanspruchen kann. Wenn Sie genug davon haben, wird dies postgresql zum Fliegen bringen. Vergessen Sie nicht, postgresql neu zu starten.
Wenn postgresql auf Linux-Systemen nicht erneut gestartet werden kann, haben Sie wahrscheinlich das kernel.shmmax-Limit erreicht. Stellen Sie es höher mit
Fügen Sie /etc/sysctl.conf einen kernel.shmmax-Eintrag hinzu, damit dies zwischen den Starts bestehen bleibt.
Eine ganze Reihe von Postgresql-Tricks finden Sie hier :
quelle
Postgres verfügt dank seiner INTERVAL-Unterstützung über eine sehr leistungsstarke Datetime-Handling-Funktion.
Zum Beispiel:
select NOW(), NOW() + '1 hour'; now | ?column? -------------------------------+------------------------------- 2009-04-18 01:37:49.116614+00 | 2009-04-18 02:37:49.116614+00 (1 row) select current_date ,(current_date + interval '1 year')::date; date | date ---------------------+---------------- 2014-10-17 | 2015-10-17 (1 row)
Sie können viele Zeichenfolgen in einen INTERVAL-Typ umwandeln.
quelle
KOPIEREN
Ich werde anfangen. Wenn ich von SQLite zu Postgres wechsle, habe ich normalerweise einige wirklich große Datenmengen. Der Schlüssel ist, Ihre Tabellen mit COPY FROM zu laden, anstatt INSERTS auszuführen. Siehe Dokumentation:
http://www.postgresql.org/docs/8.1/static/sql-copy.html
Im folgenden Beispiel wird eine Tabelle mit dem vertikalen Balken (|) als Feldtrennzeichen auf den Client kopiert:
COPY country TO STDOUT WITH DELIMITER '|';
So kopieren Sie Daten aus einer Datei in die Ländertabelle:
Siehe auch hier: Schnellere Masseneinsätze in sqlite3?
quelle
generate_series
: Endlich eine saubere Möglichkeit, Dummy-Rowsets zu generieren.Möglichkeit, einen korrelierten Wert in einer
LIMIT
Klausel einer Unterabfrage zu verwenden:SELECT ( SELECT exp_word FROM mytable OFFSET id LIMIT 1 ) FROM othertable
quelle
Eines der Dinge, die ich an Postgres wirklich mag, sind einige der in Spalten unterstützten Datentypen. Beispielsweise gibt es Spaltentypen zum Speichern von Netzwerkadressen und Arrays . Mit den entsprechenden Funktionen ( Netzwerkadressen / Arrays ) für diese Spaltentypen können Sie viele komplexe Vorgänge in Abfragen ausführen, die Sie ausführen müssen, indem Sie Ergebnisse über Code in MySQL oder anderen Datenbankmodulen verarbeiten.
quelle
Arrays sind wirklich cool, wenn man sie kennenlernt. Nehmen wir an, Sie möchten einige Hyperlinks zwischen Seiten speichern. Sie könnten damit beginnen, eine Tabelle wie diese zu erstellen:
CREATE TABLE hyper.links ( tail INT4, head INT4 );
Wenn Sie indizieren die benötigte Schwanz Spalte, und man hatte, sagen wir 200 Millionen Links-Reihen (wie wikipedia würden Sie geben), findet man sich mit einem großen Tisch und einem großen Index finden würde.
Mit PostgreSQL können Sie jedoch stattdessen dieses Tabellenformat verwenden:
CREATE TABLE hyper.links ( tail INT4, head INT4[], PRIMARY KEY(tail) );
Um alle Köpfe für einen Link zu erhalten, können Sie einen Befehl wie diesen senden (unnest () ist seit 8.4 Standard):
SELECT unnest(head) FROM hyper.links WHERE tail = $1;
Diese Abfrage ist überraschend schnell, wenn sie mit der ersten Option verglichen wird (unnest () ist schnell und der Index ist viel kleiner). Darüber hinaus belegen Ihre Tabelle und Ihr Index viel weniger RAM-Speicher und HD-Speicherplatz, insbesondere wenn Ihre Arrays so lang sind, dass sie zu einer Toast-Tabelle komprimiert werden. Arrays sind wirklich mächtig.
Hinweis: Während unnest () Zeilen aus einem Array generiert, aggregiert array_agg () Zeilen zu einem Array.
quelle
Materialisierte Ansichten sind ziemlich einfach einzurichten:
CREATE VIEW my_view AS SELECT id, AVG(my_col) FROM my_table GROUP BY id; CREATE TABLE my_matview AS SELECT * FROM my_view;
Dadurch wird eine neue Tabelle, my_matview, mit den Spalten und Werten von my_view erstellt. Trigger oder ein Cron-Skript können dann eingerichtet werden, um die Daten auf dem neuesten Stand zu halten, oder wenn Sie faul sind:
TRUNCATE my_matview; INSERT INTO my_matview SELECT * FROM my_view;
quelle
Vererbung..infact Mehrfachvererbung (wie bei der Eltern-Kind-Vererbung, nicht bei der 1-zu-1-Beziehungsvererbung, die viele Web-Frameworks bei der Arbeit mit Postgres implementieren).
PostGIS (räumliche Erweiterung), ein wunderbares Add-On, das umfassende Geometriefunktionen bietet und die Speicherung sofort koordiniert. Weit verbreitet in vielen Open-Source-Geobibliotheken (z. B. OpenLayers, MapServer, Mapnik usw.) und definitiv viel besser als die räumlichen Erweiterungen von MySQL.
Schreibvorgänge in verschiedenen Sprachen, z. B. C, Python, Perl usw. (erleichtert das Codieren in Ihrem Leben, wenn Sie Entwickler und kein Datenbankadministrator sind).
Alle Prozeduren können auch extern (als Module) gespeichert und zur Laufzeit durch angegebene Argumente aufgerufen oder importiert werden. Auf diese Weise können Sie den Code in der Quellcodeverwaltung steuern und den Code einfach debuggen.
Ein umfangreicher Katalog zu allen in Ihrer Datenbank implementierten Objekten (z. B. Tabellen, Einschränkungen, Indizes usw.).
Ich finde es immer sehr hilfreich, einige Abfragen auszuführen und alle Metainformationen abzurufen, z. B. Einschränkungsnamen und Felder, in denen sie implementiert wurden, Indexnamen usw.
Für mich ist alles sehr praktisch, wenn ich neue Daten laden oder umfangreiche Aktualisierungen in großen Tabellen durchführen muss (ich würde Trigger automatisch deaktivieren und Indizes löschen) und sie nach Abschluss der Verarbeitung einfach wieder neu erstellen muss. Jemand hat eine Handvoll dieser Fragen hervorragend geschrieben.
http://www.alberton.info/postgresql_meta_info.html
Mehrere Schemas unter einer Datenbank. Sie können sie verwenden, wenn Ihre Datenbank eine große Anzahl von Tabellen enthält. Sie können sich Schemas als Kategorien vorstellen. Alle Tabellen (unabhängig vom Schema) haben Zugriff auf alle anderen Tabellen und Funktionen in der übergeordneten Datenbank.
quelle
Sie müssen nicht lernen, wie Sie die Ausgabe "Erklären, Analysieren" entschlüsseln. Es gibt ein Tool: http://explain.depesz.com
quelle
select pg_size_pretty(200 * 1024)
quelle
PostgreSQL 9.3
gefangenem Fehlerpg_size_pretty((200 * 1024)::bigint)
pgcrypto : Mehr kryptografische Funktionen als die Kryptomodule vieler Programmiersprachen bieten, auf die alle direkt aus der Datenbank zugegriffen werden kann. Es macht kryptografische Dinge unglaublich einfach, einfach richtig zu machen.
quelle
Eine Datenbank kann kopiert werden mit:
Die Dokumentation sagt:
aber es funktioniert gut für mich und ist viel schneller als
quelle
Speicher für Wegwerfdaten / globale Variablen
Sie können einen Tabellenbereich erstellen, der sich im RAM befindet, und Tabellen (möglicherweise nicht protokolliert in 9.1) in diesem Tabellenbereich, um Wegwerfdaten / globale Variablen zu speichern, die Sie für mehrere Sitzungen freigeben möchten.
http://magazine.redhat.com/2007/12/12/tip-from-an-rhce-memory-storage-on-postgresql/
Hinweisschlösser
Diese sind in einem dunklen Bereich des Handbuchs dokumentiert:
http://www.postgresql.org/docs/9.0/interactive/functions-admin.html
Es ist gelegentlich schneller als das Erfassen einer Vielzahl von Sperren auf Zeilenebene und kann verwendet werden, um Fälle zu umgehen, in denen FOR UPDATE nicht implementiert ist (z. B. rekursive CTE-Abfragen).
quelle
UNLOGGED
Tabellen.Dies ist meine Favoritenliste mit weniger bekannten Funktionen.
Transaktions-DDL
Nahezu jede SQL-Anweisung ist in Postgres transaktional. Wenn Sie die automatische Festschreibung deaktivieren, ist Folgendes möglich:
drop table customer_orders; rollback; select * from customer_orders;
Bereichstypen und Ausschlussbeschränkungen
Meines Wissens ist Postgres das einzige RDBMS, mit dem Sie eine Einschränkung erstellen können, die prüft, ob sich zwei Bereiche überschneiden. Ein Beispiel ist eine Tabelle, die Produktpreise mit dem Datum "gültig von" und "gültig bis" enthält:
create table product_price ( price_id serial not null primary key, product_id integer not null references products, price numeric(16,4) not null, valid_during daterange not null );
NoSQL-Funktionen
Die
hstore
Erweiterung bietet einen flexiblen und sehr schnellen Schlüssel- / Wertspeicher, der verwendet werden kann, wenn Teile der Datenbank "schemalos" sein müssen. JSON ist eine weitere Option zum Speichern von Daten ohne Schema undinsert into product_price (product_id, price, valid_during) values (1, 100.0, '[2013-01-01,2014-01-01)'), (1, 90.0, '[2014-01-01,)'); -- querying is simply and can use an index on the valid_during column select price from product_price where product_id = 42 and valid_during @> date '2014-10-17';
Der Ausführungsplan für das oben Gesagte in einer Tabelle mit 700.000 Zeilen:
Um das Einfügen von Zeilen mit überlappenden Gültigkeitsbereichen zu vermeiden, kann eine einfache (und effiziente) eindeutige Einschränkung definiert werden:
alter table product_price add constraint check_price_range exclude using gist (product_id with =, valid_during with &&)
Unendlichkeit
Anstatt weit in der Zukunft ein "echtes" Datum zu verlangen, kann Postgres Daten mit unendlich vergleichen. Wenn Sie beispielsweise keinen Datumsbereich verwenden, können Sie Folgendes tun
insert into product_price (product_id, price, valid_from, valid_until) values (1, 90.0, date '2014-01-01', date 'infinity');
Beschreibbare allgemeine Tabellenausdrücke
Sie können eine einzelne Anweisung löschen, einfügen und auswählen:
with old_orders as ( delete from orders where order_date < current_date - interval '10' year returning * ), archived_rows as ( insert into archived_orders select * from old_orders returning * ) select * from archived_rows;
Mit dem obigen Befehl werden alle Bestellungen gelöscht, die älter als 10 Jahre sind, in die
archived_orders
Tabelle verschoben und dann die verschobenen Zeilen angezeigt.quelle
1.) Wenn Sie zum Abfragen eine Benachrichtigung anhängen müssen, können Sie einen verschachtelten Kommentar verwenden
SELECT /* my comments, that I would to see in PostgreSQL log */ a, b, c FROM mytab;
2.) Entfernen Sie nachgestellte Leerzeichen aus allen
text
und-varchar
Feldern in einer Datenbank.do $$ declare selectrow record; begin for selectrow in select 'UPDATE '||c.table_name||' SET '||c.COLUMN_NAME||'=TRIM('||c.COLUMN_NAME||') WHERE '||c.COLUMN_NAME||' ILIKE ''% '' ' as script from ( select table_name,COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where table_name LIKE 'tbl%' and (data_type='text' or data_type='character varying' ) ) c loop execute selectrow.script; end loop; end; $$;
3.) Wir können eine Fensterfunktion verwenden, um doppelte Zeilen sehr effektiv zu entfernen:
DELETE FROM tab WHERE id IN (SELECT id FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), id FROM tab) x WHERE x.row_number > 1);
Einige optimierte PostgreSQL-Versionen (mit ctid):
DELETE FROM tab WHERE ctid = ANY(ARRAY(SELECT ctid FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), ctid FROM tab) x WHERE x.row_number > 1));
4.) Wenn wir den Serverstatus identifizieren müssen, können wir eine Funktion verwenden:
SELECT pg_is_in_recovery();
5.) Holen Sie sich den DDL-Befehl der Funktionen.
select pg_get_functiondef((select oid from pg_proc where proname = 'f1'));
6.) Sicheres Ändern des Spaltendatentyps in PostgreSQL
create table test(id varchar ); insert into test values('1'); insert into test values('11'); insert into test values('12'); select * from test --Result-- id character varying -------------------------- 1 11 12
Sie können der obigen Tabelle entnehmen, dass ich den Datentyp "Zeichen variierend" für die
Spalte "ID" verwendet habe . Aber es war ein Fehler, weil ich immer ganze Zahlen als ID gebe. Daher ist die Verwendung von Varchar hier eine schlechte Praxis. Versuchen wir also, den Spaltentyp in eine Ganzzahl zu ändern.
ALTER TABLE test ALTER COLUMN id TYPE integer;
Aber es kehrt zurück:
Das heißt, wir können den Datentyp nicht einfach ändern, da die Daten bereits in der Spalte vorhanden sind. Da die Daten vom Typ 'zeichenvariierend' sind, können Postgres sie nicht als Ganzzahl erwarten, obwohl wir nur Ganzzahlen eingegeben haben. Wie postgres vorgeschlagen hat, können wir jetzt den Ausdruck 'USING' verwenden, um unsere Daten in Ganzzahlen umzuwandeln.
ALTER TABLE test ALTER COLUMN id TYPE integer USING (id ::integer);
Es klappt.
7.) Wissen, wer mit der Datenbank verbunden ist
Dies ist mehr oder weniger ein Überwachungsbefehl. Verwenden Sie die folgende SQL, um festzustellen, welcher Benutzer mit welcher Datenbank verbunden ist, einschließlich IP und Port:
SELECT datname,usename,client_addr,client_port FROM pg_stat_activity ;
8.) PostgreSQL-Konfigurationsdateien neu laden, ohne den Server neu zu starten
PostgreSQL-Konfigurationsparameter befinden sich in speziellen Dateien wie postgresql.conf und pg_hba.conf. Oft müssen Sie diese Parameter ändern. Damit einige Parameter wirksam werden, müssen wir die Konfigurationsdatei häufig neu laden. Ein Neustart des Servers reicht natürlich aus. In einer Produktionsumgebung ist es jedoch nicht bevorzugt, die Datenbank, die von Tausenden verwendet wird, neu zu starten, nur um einige Parameter festzulegen. In solchen Situationen können wir die Konfigurationsdateien neu laden, ohne den Server mit der folgenden Funktion neu zu starten:
select pg_reload_conf();
9.) Abrufen des Datenverzeichnispfads des aktuellen Datenbankclusters
Es ist möglich, dass in einem System mehrere Instanzen (Cluster) von PostgreSQL im Allgemeinen an verschiedenen Ports oder so eingerichtet werden. In solchen Fällen ist es eine hektische Aufgabe, herauszufinden, welches Verzeichnis (physisches Speicherverzeichnis) von welcher Instanz verwendet wird. In solchen Fällen können wir den folgenden Befehl in jeder Datenbank in dem Cluster von Interesse verwenden, um den Verzeichnispfad abzurufen:
SHOW data_directory;
Dieselbe Funktion kann zum Ändern des Datenverzeichnisses des Clusters verwendet werden, erfordert jedoch einen Neustart des Servers:
SET data_directory to new_directory_path;
10.) Finden Sie ein CHAR ist DATE oder nicht
create or replace function is_date(s varchar) returns boolean as $$ begin perform s::date; return true; exception when others then return false; end; $$ language plpgsql;
Verwendung: Folgendes gibt True zurück
select is_date('12-12-2014') select is_date('12/12/2014') select is_date('20141212') select is_date('2014.12.12') select is_date('2014,12,12')
11.) Ändern Sie den Eigentümer in PostgreSQL
12.) PGADMIN PLPGSQL DEBUGGER
Nun erklärt hier
quelle
Es ist praktisch, eine alte Datenbank umzubenennen, anstatt dies mit MySQL zu tun. Verwenden Sie einfach den folgenden Befehl:
ALTER DATABASE name RENAME TO new_name
quelle