Zastanawiam się, jaki byłby najbardziej efektywny sposób usuwania dużej liczby wierszy z PostgreSQL, ten proces byłby codziennie częścią powtarzającego się zadania masowego importowania danych (delta wstawiania + usuwania) do tabeli. Mogą być tysiące, potencjalnie miliony wierszy do usunięcia.
Mam plik kluczy podstawowych, po jednym w wierszu. Dwie opcje, o których myślałem, były zgodne z poniższymi, ale nie znam / nie rozumiem wystarczająco dużo elementów wewnętrznych PostgreSQL, aby podjąć świadomą decyzję, która byłaby najlepsza.
- Wykonaj
DELETE
zapytanie dla każdego wiersza w pliku, używając prostegoWHERE
klucza podstawowego (lub zgrupuj usuwane partien
za pomocąIN()
klauzuli) - Zaimportuj klucze podstawowe do tabeli tymczasowej za pomocą
COPY
polecenia, a następnie usuń je z tabeli głównej za pomocą łączenia
Wszelkie sugestie będą mile widziane!
postgresql
delete
bulk
Tarnfeld
źródło
źródło
Odpowiedzi:
Druga opcja jest znacznie czystsza i będzie działać wystarczająco dobrze, aby było warto. Alternatywą jest budowanie gigantycznych zapytań, których planowanie i wykonywanie będzie dość uciążliwe. Zasadniczo lepiej będzie, jeśli PostgreSQL wykona pracę tutaj. Ogólnie rzecz biorąc, znalazłem aktualizacje dziesiątek tysięcy wierszy w sposób, który opisujesz, aby zapewnić odpowiednią wydajność, ale jest jedna ważna rzecz, której należy unikać.
Aby to zrobić, użyj opcji select i join w usuniętym pliku.
W żadnym wypadku nie powinieneś robić z dużym stołem:
To zwykle powoduje, że antijoin z zagnieżdżoną pętlą powoduje, że wydajność jest raczej problematyczna. Jeśli w końcu będziesz musiał wybrać tę trasę, zrób to zamiast tego:
PostgreSQL jest zwykle całkiem dobry w unikaniu złych planów, ale wciąż istnieją przypadki związane z zewnętrznymi złączeniami, które mogą mieć duży wpływ na dobre i złe plany.
Wędruje to nieco dalej, ale wydaje mi się, że warto o tym wspomnieć, ponieważ łatwo jest przejść z IN do NOT IN i oglądać zbiornik wydajności zapytania.
źródło
IN ( select id from foo except select id from rows_to_keep )
Zobacz postgresql.org/docs/9.4/static/queries-union.htmlNatknąłem się na to pytanie, ponieważ miałem podobny problem. Czyszczę bazę danych, która ma ponad 300 milionów wierszy, ostateczna baza danych będzie miała tylko około 30% oryginalnych danych. Jeśli masz do czynienia z podobnym scenariuszem, w rzeczywistości łatwiej jest wstawić do nowej tabeli i ponownie zaindeksować zamiast usuwać.
Zrób coś takiego
Dzięki odpowiedniemu indeksowaniu na foo i pasku możesz uniknąć skanowania Seq.
Następnie musiałbyś ponownie zaindeksować i zmienić nazwę tabeli.
źródło