Jak mogę się dowiedzieć, jak daleko jest moje zapytanie PostgreSQL?


35

Mam całkiem niezłe pojęcie, ile wierszy faktycznie przetworzy moje zapytanie SELECT ... INTO (np. Wiem, ile zmaterializuje się).

Rozumiem, że Postgres nie powie mi procentowej kompletności, czy istnieje sposób (głęboko ukryty w logach, tabelach systemowych itp.), Że mogę dowiedzieć się, ile wierszy zostało wpompowanych do tabeli docelowej lub odczytanych przez zapytanie SELECT ?

Odpowiedzi:


33

Jak wspomniał Daniel Vérité, wydaje się, że nie ma ogólnego rozwiązania. Podczas ładowania danych do tabeli z pliku można zastosować następującą technikę, aby uzyskać postęp ładowania.

Pasek postępu konsoli poleceń COPY

Utwórz pustą tabelę.

CREATE TABLE mytest (n int);

Utwórz plik danych z 10 milionami linii do załadowania do tabeli.

$ seq 10000000 > /tmp/data.txt

Załaduj dane z pliku do tabeli i wyświetl pasek postępu.

$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"

Próbny

wprowadź opis zdjęcia tutaj

Jak to działa

Za pomocą opcji STDIN poleceń kopiowania możemy wprowadzić dane do operacji kopiowania z innego procesu. Komenda pv wyświetli plik i będzie śledzić jego postęp, wyświetlając pasek postępu, ETA, całkowity czas, jaki upłynął i szybkość transferu danych.

Graficzny pasek postępu polecenia KOPIUJ

Korzystając z tej samej ogólnej techniki, możemy wyświetlić pasek postępu w aplikacji graficznej lub aplikacji internetowej. Użycie Pythona na przykład moduł psycopg2 pozwala wywołać polecenie kopiowania z wybranym obiektem pliku. Następnie możesz śledzić, ile części Twojego pliku pliku zostało odczytane i wyświetlić pasek postępu.


2
Nie spotkałem się wcześniej z pvpoleceniem i nie było ono domyślnie instalowane na moim serwerze Debian, ale jest w repozytorium. Opis mówi „pv (Pipe Viewer) można wstawić do dowolnego normalnego potoku między dwoma procesami, aby wizualnie wskazać, jak szybko dane przechodzą”. Bardzo przydatne polecenie!
Richard Turner

27

Wydaje się, że nie ma ogólnej, obsługiwanej metody, ale istnieją pewne sztuczki, których można użyć w ograniczonych kontekstach do oceny postępu pojedynczego zapytania. Tutaj są niektóre z nich.

Sekwencje

Gdy zapytanie SELECT lub UPDATE zawiera dowolne zapytanie nextval(sequence_name)lub INSERT ma nextvaldomyślną kolumnę docelową , bieżąca wartość sekwencji może być wielokrotnie sprawdzana w innej sesji za pomocą SELECT sequence_name.last_value. Działa, ponieważ sekwencje nie są ograniczone transakcjami. Jeśli plan wykonania jest taki, że sekwencja jest zwiększana liniowo podczas zapytania, można go użyć jako wskaźnika postępu.

pgstattuple

Moduł contg pgstattuple zapewnia funkcje, które mogą podglądać bezpośrednio na stronach danych. Wygląda na to, że kiedy krotki są wstawiane do pustej tabeli i jeszcze nie zatwierdzone, są liczone w dead_tuple_countpolu z pgstattuplefunkcji.

Demo z wersją 9.1: utwórz pustą tabelę

CREATE TABLE tt AS (n numeric);

Wstawmy do niego 10 mln wierszy:

INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);

W innej sesji sprawdzaj pgstattuple co sekundę podczas wstawiania:

$ while true;
   do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
   sleep 1;
  done

Wyniki:

0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0

Po zakończeniu wstawiania spada do 0 (wszystkie krotki stają się widoczne i aktywne).

Tej sztuczki można również użyć, gdy tabela nie jest świeżo utworzona, ale wartość początkowa dead_tuple_countmoże mieć niezerową wartość i może również zmieniać się równocześnie, jeśli trwa inna czynność zapisu, taka jak autovacuum (przypuszczalnie? Nie wiesz, jaki poziom współbieżność oczekiwana z autovacuum).

Jednak nie można go użyć, jeśli tabela jest tworzona przez samą instrukcję ( CREATE TABLE ... AS SELECTlub SELECT * INTO newtable), ponieważ tworzenie jest transakcyjne. Obejściem tego problemu byłoby utworzenie tabeli bez wierszy (dodanie LIMIT 0) i wypełnienie jej w następnej transakcji.

Pamiętaj, że pgstattuplenie jest darmowy: skanuje cały stół przy każdym połączeniu. Również ogranicza się do superużytkowników.

Licznik niestandardowy

Na blogu Pavla Stehule'a zapewnia on funkcję licznika zaimplementowaną w C, która podnosi UWAGI przy określonej liczbie wykonań. Musisz w jakiś sposób połączyć funkcję z zapytaniem, aby wykonawca mógł je wywołać. Powiadomienia są wysyłane podczas zapytania i nie potrzebują osobnej sesji, tylko klient SQL, który je wyświetla ( psqljest oczywistym kandydatem).

Przykład przeróbki INSERT INTO w celu podniesienia uwagi:

/* transformation */
INSERT INTO destination_table
   SELECT (r).*
  FROM (SELECT counter(to_destination_table(_source), 1000, true) r
           FROM source _source) x

Powiązane pytanie dotyczące przepływu stosu dla funkcji:
Jak zgłosić postęp od długotrwałej funkcji PostgreSQL do klienta

Przyszłe opcje?

Od maja 2017 r. Do społeczności programistów została dostarczona obiecująca łatka: [PATCH v2] Polecenie Progress do monitorowania postępu długotrwałych zapytań SQL

co może skończyć jako ogólne rozwiązanie w PostgreSQL 11 lub nowszym. Użytkownicy, którzy chcą uczestniczyć w funkcjach w toku, mogą zastosować najnowszą wersję poprawki i wypróbować proponowane PROGRESSpolecenie.


3

Dopóki funkcjonalność raportu postępu nie zostanie rozszerzona, jak wspomniał @AmirAliAkbari w swojej odpowiedzi, oto obejście obejścia na poziomie systemu operacyjnego.

Działa to tylko w systemach Linux, ale prawdopodobnie istnieją łatwo dostępne w Internecie podobne rozwiązania dla dowolnych systemów operacyjnych.

Największą zaletą, a także wadą PostgreSQL, że wszystkie jej backendów są proste jednowątkowy procesy, za pomocą lseek(), read()i write()manipulować swoje pliki stole, podczas gdy są one oddziałujących na wspólną mem i zamków.

Powoduje to, że wszystkie procesy zaplecza działają zawsze na jednym zapytaniu, które można łatwo znaleźć i łatwo straced.

Po pierwsze, możesz zobaczyć backend PID z SELECT * FROM pg_stat_activity;:

29805270 | dbname  | 20019 |    16384 | username  |                  |             |                 |          -1 | 2018-09-19 21:31:57.68234+02  | 2018-09-19 21:31:59.435376+02 | 2018-09-\
20 00:34:30.892382+02 | 2018-09-20 00:34:30.892386+02 | Client          | ClientRead | active              |       92778 |        92778 |  INSERT INTO ...something...

Trzecia kolumna to pid. W PostgreSQL jest taki sam jak pid procesu pend dla backendu.

Następnie możesz utworzyć ścieżkę, na przykład przez strace -p 20019 -s 8192: ( -s 8192jest przydatny, ponieważ postgresql działa z blokami o długości 8192 bajtów).

sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
recvfrom(10, "Q\0\0\1\267 INSERT <removed by @peterh>", 8192, 0, NULL, NULL) = 440
sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
lseek(298, 343634345)...
read(298, "<block data which was read in>"....
write(298, "<block data which was written out>"...

Znaczenie:

  • sendtozdarza się, jeśli backend odpowiada coś na klienta. W tym przykładzie odpowiada na wynik INSERTzapytania.
  • recvfromdzieje się, jeśli backend pobiera coś od klienta. Zazwyczaj jest to nowe zapytanie, w tym przykładzie, jeszcze jedno INSERT.
  • lseek dzieje się, jeśli backend przełącza pozycję w pliku tabeli.
  • read dzieje się, jeśli backend odczytuje blok z pliku tabeli.
  • write dzieje się, jeśli backend zapisuje blok w pliku tabeli.

W przypadku readi writemożesz również zobaczyć zawartość tego bloku w tabeli. Bardzo pomaga zrozumieć, co robi i gdzie to jest.

W przypadku recvfrommożesz zobaczyć rzeczywiste zapytanie jakie ma backend.


2

Jak powiedziano w innych odpowiedziach, obecnie ogólnie nie ma bezpośredniego sposobu na raportowanie postępów.

PostgreSQL ma możliwość raportowania postępu niektórych poleceń podczas wykonywania poleceń. Obecnie jedynym poleceniem obsługującym raportowanie postępu jest VACUUM. To może zostać rozszerzone w przyszłości.

Jednak począwszy od 9.6, przy każdym VACUUMuruchomieniu pg_stat_progress_vacuumwidok będzie zawierał jeden wiersz dla każdego backendu (w tym procesów roboczych autovacuum), który obecnie odkurza. Dalsze szczegóły pg_stat_progress_vacuummożna znaleźć w dokumentacji: 27.4 Raportowanie postępów .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.