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.