2012-10-17 18 views
8

Mam duży stół z 10-milionowymi rzędami. I potrzebuję uzyskać wartość statystyczną dla każdego rzędu. Mam funkcję, która generuje tę wartość, na przykład GetStatistic(uuid). Funkcja ta działa bardzo powoli i nie zmienia wartości wynik często, więc stworzyłem kolumnę Statistic w moim stole, a raz dziennie wykonać kwerendę tak:Postgresql. Czy można uruchomić kwerendę aktualizacji równolegle?

UPDATE MyTable SET Statistic = GetStatistic(ID); 

aw wybranych zapytań użyć kolumny Statistic bez wywoływania GetStatistic Funkcje.

Problem polega na tym, że mój serwer produkcyjny ma 64 procesory i dużo pamięci, więc prawie wszystkie bazy danych mogą być buforowane do pamięci RAM, ale zapytanie to wykorzystuje tylko jeden procesor i wymaga 2 lub 3 godzin do wykonania.

Funkcja GetStatistic korzysta z tabeli, która jest stała podczas każdego wykonania zapytania UPDATE. Czy mogę zmodyfikować zapytanie, aby uzyskać postgre, aby obliczyć GetStatistic równolegle dla różnych wierszy jednocześnie, używając wszystkich dostępnych procesorów?

+0

Dlaczego warto skorzystać z funkcji, czy jest coś, czego nie można osiągnąć przez zwykły SQL? Czy funkcja potrzebuje tylko wartości z bieżącego wiersza, czy też obejmuje również inne źródła danych (: = tabele)? BTW: pokaż nam funkcję. – wildplasser

+0

Sprawdź plan tego zapytania, zobaczysz, że ta funkcja nazywa się 10M razy. Może lepiej byłoby napisać to w czystym SQL i może być znacznie szybciej. –

Odpowiedz

9

PostgreSQL wykonuje każde zapytanie w jednym backendie, który jest procesem z pojedynczym wątkiem. Nie może użyć więcej niż jednego procesora dla zapytania. Jest także nieco ograniczony w tym, co może osiągnąć współbieżność we/wy w ramach pojedynczej kwerendy, wykonując tylko współbieżne operacje we/wy dla skanów indeksu bitmap i w inny sposób polegając na systemie operacyjnym i systemie dyskowym dla współbieżnych operacji we/wy.

Pg sprawdza się przy równoczesnym ładowaniu wielu mniejszych zapytań i łatwo nasycić system w ten sposób, po prostu nie jest tak dobry w tworzeniu najlepszych zasobów systemowych dla jednego lub dwóch naprawdę dużych zapytań.

Co możesz zrobić, to podzielić pracę na kawałki i rozdać je pracownikom. Pan wspomniał o tym z:

mogę zmodyfikować kwerendę, aby uzyskać Postgre obliczyć GetStatistic w Paralel różnych rzędach jednocześnie, wykorzystując wszystkie dostępna CPU?

Istnieje wiele narzędzi, jak DBlink, PL/Proxy, pgbouncer i PgPool-II, które są zaprojektowane, aby pomóc w tego rodzaju pracy. Alternatywnie można po prostu zrobić to samemu, zaczynając (powiedzmy) 8 pracowników, z których każdy łączy się z bazą danych i wykonuje instrukcje UPDATE ... WHERE id BETWEEN ? AND ? z zachodzącymi na siebie zakresami ID. Bardziej wyrafinowaną opcją jest posiadanie kontrolera kolejki rozdającego zakresy około 1000 identyfikatorów pracownikom, którzy to zakres wynoszą, a następnie proszą o nowy.

Należy zauważyć, że 64 procesory nie oznaczają, że 64 równoczesnych pracowników jest idealna. Dysk I/O jest również czynnikiem, jeśli chodzi o pisanie. Możesz nieco wydłużyć koszty operacji wejścia/wyjścia, jeśli skonfigurujesz transakcje UPDATE na korzystanie z commit_delay i (jeśli jest to bezpieczne dla wymagań biznesowych dla tych danych) synchronous_commit = 'off', wówczas obciążenie z synchronizacji powinno zostać znacznie zmniejszone. Niemniej jednak "prawdopodobnie najlepsza wydajność zostanie osiągnięta znacznie poniżej 64 równoczesnych pracowników.

Jest wysoce prawdopodobne, że twoja funkcja GetStatistic może być znacznie szybsza, przekształcając ją w nieodwracalną funkcję lub widok SQL, a nie to, co jest prawdopodobnie pętlą-ciężką proceduralną funkcją PL/pgSQL, którą właśnie jest. Może ci pomóc, gdybyś pokazała tę funkcję.

Powiązane problemy