Baza Postgres jest mi dość bliska ponieważ jest to jedna z baz, z której korzystamy we Freeconecie. Z tego powodu dość uważnie obserwujemy co się zmieniło w kolejnych wersjach i z jakich nowych funkcjonalności będzie można skorzystać.
Niecały tydzień temu na stronie Postgres’a została udostępniona wersja 8.4. Wersja jest za ‘młoda’ żeby użyć ją w rozwiązaniach produkcyjnych, jednakże dokładnie przeanalizowałem co uległo zmianie i w tym artykule chciałbym zwrócić waszą uwagę na najciekawsze (moim zdaniem) nowe funkcjonalności. Ze względu, na to że głównymi czytelnikami bloga są programiści mam nadzieje, że dla części artykuł będzie interesujący. Poniżej lista nowości.
Windowing Function
Są to operacje pozwalające na dokonanie obliczeń na zbiorze wierszy jednakże funkcje umożliwiają odnieść wynik do bieżącego wiersza. Funkcje działają podobnie do funkcji grupujących z tą różnicą, że wynik nie jest grupowany do jednego wiersza. Bardziej zrozumiałe to będzie jeśli użyje przykładu z dokumentacji.
W wyniku takiego zapytania
SELECT nazawaoddzialu, empno, zarobki, avg(zarobki) OVER (PARTITION BY nazwaoddzialu) FROM empsalary;
otrzymamy
| nazwaoddzialu |
empno |
zarobki |
avg |
| develop |
11 |
5200 |
5020.0000000000000000 |
| develop |
7 |
4200 |
5020.0000000000000000 |
| develop |
9 |
4500 |
5020.0000000000000000 |
| develop |
8 |
6000 |
5020.0000000000000000 |
| develop |
10 |
5200 |
5020.0000000000000000 |
| personnel |
5 |
3500 |
3700.0000000000000000 |
| personnel |
2 |
3900 |
3700.0000000000000000 |
Pierwsze trzy kolumny są kolumnami tabeli empsalary, natomiast ostatnia kolumna jest średnią z kolumny zarobki z tym, że ta średnia podawana jest przy każdym wierszy pracownika z danego nazwaoddzialu i liczona jest z wierszy mających tą samą wartość nazwaoddziału. Pełna lista dostępnych funkcji można znaleźć na stronie http://www.postgresql.org/docs/8.4/interactive/functions-window.html z przykładowych funkcji można wymienić row_number() wyświetlającą numer porządkowy w danym ‘okienku’, co pozwala na numeracje wierszy.
Common Table Expressions & Recursive Queries
Jest to głównie odmienny zapis podzapytań dla skomplikowanych zapytań SQL. Przykładowe zapytanie z dokumentacji Postgresa
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region
), top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales; (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region,
product,
SUM(quantity) AS product_units,
SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;
W tym zapytaniu fragment definiujący regional_sales jest jakby podstawiany do obliczania top_regional a wartość
top_regional podstawiana jest do głównego zapytania. Podane zapytanie można przepisać tak żeby nie zawierała konstrukcji WITH jednak wtedy mamy dwa poziomy sub-select’ów. Konstrukcje WITH możemy potraktować jako tymczasową tablice. Zupełnie nową funkcjonalność daje konstrukcja WITH RECURSIVE
Przykład z dokumentacji:
WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t;
Podany zapytanie zsumuje liczby od 1 do 100, nie jest to może zbyt praktyczny przykład ale jeden z prostszych. Tego typu konstrukcje w SQL znajdą zastosowanie w trakcie operacji na danych, które są zdefiniowane w postaci drzewa albo są przechowywane w sposób hierarchiczny.
Visibility Map
Wprowadzono kolejne poprawki minimalizujące potrzeby VACUUMów. W systemach czasu rzeczywistego musimy maksymalnie unikać tej operacji ponieważ istotnie blokuje inne operacje na bazie.
Nowe funkcjonalności w monitoringu aktywności bazy
Pojawiła się możliwość monitorowania czasu i ilości wywołań procedur bazodanowych jak również samych zapytań SQL. Co istotne statystyki przechowywane są w bazie. Funkcjonalność bardzo przydatna, ponieważ dotychczas ‘długie zapytania’ można było rejestrować jedynie w pliku log bazy danych, dodatkowo rozwiązanie pozwalało monitorować jedynie zapytania, które trwają dłużej niż zdefiniowana wartość. W sytuacji gdy dane zapytanie było wykonywane bardzo często ale nie trwało dłużej niż określony czas taki przypadek ‘wymykał się’ z analizy.
RETURNS TABLE
W wersji 8.4 oprócz możliwości zwracania typów podstawowych takich jak INT,NUMERIC i typów złożonych (ang.composite) zdefiniowanych w postaci typów i definicji opartych o istniejące tabele (chodzi o konstrukcje z SETOF) dodano konstrukcje RETURNS TABLE. Poniżej przykład użycia takiej konstrukcji:
CREATE OR REPLACE FUNCTION test_procedure() RETURNS TABLE (rv_id INT8,rv_test VARCHAR)
AS $$
BEGIN
RETURN QUERY SELECT id as t_id, test as t_test FROM test_table;
END;
Zaletą takiej konstrukcji jest, to że nie musimy tworzyć typu specjalnie na potrzeby zwracania rezultatów z funkcji. Teoretycznie można w wielu sytuacjach użyć takiej konstrukcji
CREATE OR REPLACE FUNCTION test_procedure() RETURN SETOF test_table
gdzie test_table jest tablicą. Problem może się pojawić gdy zmieni się struktura bazy danych - funkcja może raportować błędy o tym, że definicja parametrów zwracanych jest inna niż to co faktycznie zwracamy z funkcji. Problem ten zgłosiłem dwa razy na grupę użytkowników Postgresa
jednak innych rad niż przeładowanie bazy nie było (oryginalny post na grupie).
Parametr -j w pg_restore
Program pg_restore (służący do odtwarzania bazy z pliku) można wywołać z parametrem -j. Tą opcje regulujemy ile równoległych procesów będzie importować dane do bazy. Według informacji znalezionych na sieci prędkość importu może wzrosnąć nawet ośmiokrotnie co jest wielkością niemałą przy odtwarzaniu naprawdę dużych baz.
Osoby chcące poznać wszystkie zmiany, które pojawiły się w Postgres’ie 8.4 zapraszam na strone http://www.postgresql.org/about/press/features84.html .