Czy istnieje systematyczny sposób, aby zmusić PostgreSQL do załadowania określonej tabeli do pamięci lub przynajmniej odczytania jej z dysku, aby system mógł ją buforować?
Czy istnieje systematyczny sposób, aby zmusić PostgreSQL do załadowania określonej tabeli do pamięci lub przynajmniej odczytania jej z dysku, aby system mógł ją buforować?
Odpowiedzi:
Możesz być zainteresowany jednym z tematów list mailowych , na który odpowiada Tom Lane (główny programista):
[..] Ale moim zdaniem ludzie, którzy myślą, że są mądrzejsi niż algorytm buforowania LRU, zwykle się mylą. Jeśli stół jest bardzo intensywnie używany, pozostanie w pamięci w porządku. Jeśli zgodnie z algorytmem LRU nie jest wystarczająco mocno wykorzystywany do pozostawania w pamięci, być może przestrzeń pamięci naprawdę powinna zostać wydana na coś innego. [..]
Może Cię również zainteresować pytanie SO: https://stackoverflow.com/questions/486154/postgresql-temporary-tables, a może bardziej odpowiedni https://stackoverflow.com/questions/407006/need-to-load-the -whole-postgresql-database-into-the-ram
Postgres 9.4 w końcu dodał rozszerzenie do wstępnego ładowania danych ze relacji do pamięci podręcznej systemu operacyjnego lub bufora bazy danych (do wyboru):
pg_prewarm
Pozwala to szybciej osiągnąć pełną wydajność operacyjną.
Uruchom raz w bazie danych (szczegółowe instrukcje tutaj ):
CREATE EXTENSION pg_prewarm;
Następnie łatwo jest wstępnie załadować dowolną relację. Podstawowy przykład:
SELECT pg_prewarm('my_tbl');
Znajduje pierwszą tabelę o nazwie podanej my_tbl
w ścieżce wyszukiwania i ładuje ją do pamięci podręcznej bufora Postgres
Lub:
SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');
prefetch
wydaje asynchroniczne żądania pobierania wstępnego do systemu operacyjnego, jeśli jest to obsługiwane, lub w przeciwnym razie zgłasza błąd.read
odczytuje żądany zakres bloków; w przeciwieństwie doprefetch
tego jest synchroniczny i obsługiwany na wszystkich platformach i kompilacjach, ale może być wolniejszy.buffer
wczytuje żądany zakres bloków do bufora bufora bazy danych.
Wartość domyślna to buffer
, która ma największy wpływ (wyższy koszt, najlepszy efekt).
Przeczytaj instrukcję, aby uzyskać więcej informacji , cytaty są stamtąd.
Depesz też o tym bloguje .
W ogólnym przypadku, jeśli masz wystarczającą ilość pamięci RAM, możesz ogólnie zaufać usłudze bazy danych, aby dobrze wykonywać czynności, których regularnie używasz w pamięci RAM. Niektóre systemy pozwalają wskazać, że tabela powinna zawsze znajdować się w pamięci RAM (co jest przydatne w przypadku małych tabel, które nie są często używane, ale kiedy są używane, ważne jest, aby odpowiadały tak szybko, jak to możliwe), ale jeśli pgsql ma takie wskazówki dotyczące tabeli musisz być bardzo ostrożny z ich używaniem, ponieważ zmniejszasz ilość dostępnej pamięci do buforowania czegokolwiek innego, aby spowolnić całą aplikację.
Jeśli chcesz uruchomić pamięć podręczną strony bazy danych podczas uruchamiania (na przykład po ponownym uruchomieniu lub innej operacji konserwacji, która powoduje, że DB zapomina o wszystkim, co jest buforowane), to napisz skrypt, który wykonuje następujące czynności:
SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>
(ten ostatni krok powtarza się dla każdego indeksu lub kursu i uważaj, aby pola w klauzuli ORDER BY były w odpowiedniej kolejności)
Po uruchomieniu powyższego każda strona danych i indeksu powinna zostać przeczytana i tak będzie w pamięci podręcznej strony RAM (przynajmniej na razie). Mamy takie skrypty dla naszych baz danych aplikacji, które są uruchamiane po ponownym uruchomieniu, aby pierwsi użytkownicy logujący się później do systemu nie reagowali wolniej. Lepiej odręcznie pisz dowolny taki skrypt, zamiast skanować tabele definicji db (jak sys.objects
/ sys.indexes
/ sys.columns
w MSSQL), wtedy możesz selektywnie skanować najczęściej używane indeksy, zamiast skanować wszystko, co zajmie dłużej.
SELECT * FROM schema.table
i zobaczyłem, że ładuje całą tabelę 60GiB do mojej pamięci podręcznej bufora PostgreSQL 100GiB.
Miałem podobny problem:
po zrestartowaniu usługi serwera i porzuceniu wszystkich danych kasowanych, wiele zapytań wywoływanych po raz pierwszy było naprawdę bardzo powolnych, ze względu na specyficzną złożoność zapytań, do momentu wykonania wszystkich niezbędnych indeksów i danych. oznacza to na przykład, że użytkownicy muszą trafić raz „każdy element” (czas wykonania 1-3 sekund) i powiązane dane z 50 milionów wierszy, aby użytkownicy nie doświadczyli już żadnych niepożądanych opóźnień. Pierwsze irytujące zawieszanie się zajmuje użytkownikom pierwsze 3 godziny, aż większość używanych danych zostanie spieniężona, a programy rujnują wydajność na najwyższym poziomie, a nawet koniec, 2 dni kilka nagłych krótkich opóźnień, gdy uderzają mniej danych za pierwszym razem ... , dla danych statystycznych itp.
Aby rozwiązać ten problem, napisałem mały skrypt Pythona, który wykonuje selekcje na najcięższych tabelach z dużymi indeksami. Uruchomienie trwało 15 minut i nie opóźniało działania.
Hmmm, może pomóc polecenie COPY. Wystarczy wykonać KOPIUJ, aby przejść do standardowego wyjścia i odczytać z niego. Można to zrobić za pomocą pg_dump:
pg_dump -U <user> -t <table> <database> > /dev/null
Innym sposobem jest znalezienie wszystkich plików tabel i uruchomienie cat <files> > /dev/null
.
Oto przykład, jak uzyskać nazwy plików tabel:
# SELECT oid, datname FROM pg_database ;
oid | datname
-------+-----------
<...>
16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
oid | relname
-------+---------
24576 | fn
(1 row)
-- oid of our table is 24576
więc plik (i) tabeli to / path / to / pgsql / data / base / 16384/24576 *
Możesz także chcieć czytać indeksy i tosty, a także pobierać ich Oids w ten sam sposób.
BTW, dlaczego go potrzebujesz? Uważam, że postgresql i system operacyjny są wystarczająco inteligentne, aby buforować najgorętsze dane i utrzymywać dobrą. wydajność pamięci podręcznej.
Używam RamDrive z QSoft, który został przetestowany jako najszybszy ramdysk dla systemu Windows. Właśnie użyłem
initdb -D e:\data
gdzie e: \ jest miejscem RamDisk.