PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wykonywanie sekwencji i seriali w Postgres-XL

W Postgres-XL sekwencje są utrzymywane w Global Transaction Manager (GTM), aby zapewnić, że przypisywane są im wartości nie powodujące konfliktu, gdy są one zwiększane z wielu węzłów. Zwiększa to znaczne obciążenie dla zapytania wykonującego tysiące INSERT w tabeli z kolumną szeregową, zwiększając sekwencję pojedynczo i wykonując objazdową sieć do GTM, dla każdej INSERT.

Shaun Thomas w niedawnym blogu narzekał, że INSERTy działają wolniej na Postgres-XL w porównaniu z waniliowym PostgreSQL. Istnieje już sposób na poprawę wydajności sekwencji, ale najwyraźniej nie jest on dobrze reklamowany. Pomyślałem, że to dobra okazja, aby wyjaśnić tę funkcję.

Postgres-XL udostępnia konfigurowalny przez użytkownika GUC o nazwie sequence_range . Każdy backend żąda bloku wartości sekwencji kontrolowanych przez ten GUC. Biorąc pod uwagę, że COPY jest powszechnie używane do zbiorczego ładowania danych w Postgresie, Postgres-XL automatycznie nadpisuje ten GUC podczas operacji COPY i ustawia go na 1000, co znacznie poprawia wydajność COPY. Niestety, w przypadku zwykłych WSTAWEK wartością domyślną jest 1 i chyba że użytkownik wyraźnie ustawi sequence_range do rozsądnie wyższej wartości, ucierpi wydajność INSERT. Oto przykład, używając tego samego przykładowego schematu, którego użył Shaun w swoim poście na blogu.

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

Więc odpowiednio ustawiając sequence_range do 1000, wydajność zapytania INSERT poprawiła się prawie 30-krotnie.

Gdy ta funkcja została dodana, domyślna wartość parametru GUC zakres_sekwencji została ustawiona na 1, ponieważ może to pozostawić luki w wartościach sekwencji. Ale patrząc na implikacje wydajnościowe w bardzo powszechnym przypadku użycia, zdecydowaliśmy się zwiększyć wartość domyślną do 1000, co zostało teraz zatwierdzone w gałęzi XL9_5_STABLE repozytorium.

Należy zauważyć, że chociaż wysoka wartość sequence_range poprawi wydajność sekwencji i seriali, może również pozostawić duże dziury w zakresach sekwencji, ponieważ zakresy sekwencji są buforowane na poziomie zaplecza. Aby rozwiązać ten problem, Postgres-XL rozpoczyna się od określonej wartości parametru CACHE używanej podczas tworzenia sekwencji i podwaja ją za każdym razem (ograniczone przez zakres_sekwencji), jeśli sekwencje są zużywane z bardzo dużą szybkością.

Podobną poprawę można również osiągnąć, zwiększając wartość parametru CACHE sekwencji, tak aby porcja wartości sekwencji była buforowana na poziomie zaplecza. Poniższy przykład pokazuje, jak to zrobić dla kolumny szeregowej. Ale sequence_range GUC zapewnia łatwy sposób na zastąpienie globalnych wartości domyślnych, a także zapewnia, że ​​sekwencje są buforowane tylko wtedy, gdy są bardzo szybko zwiększane.

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

Możesz wybrać dowolną z tych technik, aby poprawić wydajność. Chociaż teraz domyślna wartość sequence_range zmieniono na 1000, niewielu użytkowników może zauważyć różnicę w wydajności.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Uzyskaj identyfikator ostatniej wkładki po przygotowanej wkładce z PDO

  2. PostgreSQL nie akceptuje aliasów kolumn w klauzuli WHERE

  3. Jak ZMIENIĆ tabelę PostgreSQL i uczynić kolumnę unikalną?

  4. Wyszukiwanie pełnotekstowe od PostgreSQL 8.3

  5. Obsada typu danych Postgres