sql >> Database >  >> RDS >> PostgreSQL

Uitvoering van sequenties en series in Postgres-XL

In Postgres-XL worden sequenties bijgehouden in de Global Transaction Manager (GTM) om ervoor te zorgen dat ze niet-conflicterende waarden krijgen wanneer ze worden verhoogd vanaf meerdere knooppunten. Dit voegt aanzienlijke overhead toe voor een query die duizenden INSERT's uitvoert in een tabel met een seriële kolom, waarbij de reeks één voor één wordt verhoogd en voor elke INSERT een netwerkrondreis naar de GTM wordt gemaakt.

Shaun Thomas klaagde in een recente blog over het feit dat INSERT's veel langzamer werken op Postgres-XL in vergelijking met vanille PostgreSQL. Er is al een manier om de prestaties van sequenties te verbeteren, maar daar wordt duidelijk niet goed over geadverteerd. Ik dacht dat dit een goede gelegenheid was om de faciliteit uit te leggen.

Postgres-XL biedt een door de gebruiker instelbare GUC genaamd sequence_range . Elke backend vraagt ​​om een ​​blok met sequentiewaarden zoals beheerd door deze GUC. Aangezien COPY in de volksmond wordt gebruikt om gegevens in Postgres in bulk te laden, heft Postgres-XL deze GUC automatisch op tijdens de COPY-bewerking en stelt deze in op 1000, waardoor de COPY-prestaties drastisch worden verbeterd. Helaas is de standaardwaarde voor reguliere INSERT's 1 en tenzij de gebruiker expliciet sequence_range instelt naar een redelijk hogere waarde, lijden INSERT-prestaties. Hier is een voorbeeld, met hetzelfde voorbeeldschema als gebruikt door Shaun in zijn blogpost.

CREATE TABLE sensor_log (
  sensor_log_id  SERIAL PRIMARY KEY,
  location       VARCHAR NOT NULL,
  reading        BIGINT NOT NULL,
  reading_date   TIMESTAMP NOT NULL
) DISTRIBUTE BY HASH (sensor_log_id);

postgres=# \timing
Timing is on.
postgres=# INSERT INTO sensor_log (location, reading, reading_date)                                                                                                                         SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL                                                                                                                    FROM generate_series(1, 40000) s(id);
INSERT 0 40000
Time: 12067.911 ms

postgres=# set sequence_range TO 1000;
SET
Time: 1.231 ms
postgres=# INSERT INTO sensor_log (location, reading, reading_date)                                                                                                                         SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL                                                                                                                    FROM generate_series(1, 40000) s(id);
INSERT 0 40000
Time: 397.406 ms

Dus door sequence_range op de juiste manier in te stellen tot 1000 zijn de prestaties van de INSERT-query bijna 30 keer verbeterd.

Toen deze functie werd toegevoegd, was de standaardwaarde van sequence_range GUC ingesteld op 1 omdat het gaten in de reekswaarden kan achterlaten. Maar kijkend naar de prestatie-implicaties voor een veelvoorkomend gebruik, hebben we besloten om de standaardwaarde te verhogen naar 1000 en dit is nu vastgelegd in de XL9_5_STABLE-tak van de repository.

Het is belangrijk op te merken dat hoewel een hoge waarde van sequence_range zal de prestaties voor sequenties en series verbeteren, het kan ook grote gaten in sequentiebereiken achterlaten, aangezien de sequentiebereiken op backend-niveau in de cache worden opgeslagen. Om dit probleem aan te pakken, begint Postgres-XL met de gespecificeerde CACHE-parameterwaarde die wordt gebruikt bij het maken van de reeks en verdubbelt deze elke keer (beperkt door reeks_bereik) als reeksen met een zeer hoge snelheid worden verbruikt.

Een vergelijkbare verbetering kan ook worden bereikt door de CACHE-parameterwaarde van de reeks te verhogen, zodat een deel van de reekswaarden op het backend-niveau in de cache wordt opgeslagen. Het volgende voorbeeld laat zien hoe u dat doet voor een seriële kolom. Maar de sequence_range GUC biedt een gemakkelijke manier om de algemene standaard te negeren en zorgt er ook voor dat de reeksen alleen in de cache worden opgeslagen als ze zeer snel worden verhoogd.

postgres=# ALTER SEQUENCE sensor_log_sensor_log_id_seq CACHE 1000;                                                                                                             ALTER SEQUENCE
Time: 8.683 ms
postgres=# SET sequence_range TO 1;
SET
Time: 2.341 ms
postgres=# INSERT INTO sensor_log (location, reading, reading_date)                                                                                                            SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL                                                                                                                  FROM generate_series(1, 40000) s(id);
INSERT 0 40000
Time: 418.068 ms

U kunt elk van deze technieken kiezen om de prestaties te verbeteren. Hoewel nu de standaardwaarde van sequence_range is gewijzigd in 1000, zullen niet veel gebruikers het verschil in prestatie zien.


  1. Relationele versus niet-relationele databases:wat is het verschil?

  2. JDBC Batch invoegen uitzondering afhandeling

  3. Hoe breid ik door komma's gescheiden waarden uit in afzonderlijke rijen met SQL Server 2005?

  4. 8 manieren om minuten toe te voegen aan een datetime in MariaDB