CodeGym /Kursy /SQL SELF /Optymalizacja masowego ładowania danych

Optymalizacja masowego ładowania danych

SQL SELF
Poziom 24, Lekcja 3
Dostępny

Wyobraź sobie, że musisz załadować milion wierszy danych. Jeśli zrobisz to powoli, twój serwer będzie długo zajęty, użytkownicy mogą zauważyć spowolnienie bazy danych, a co gorsza — twoja kawa może wystygnąć zanim skończysz. Optymalizacja pozwala uniknąć przeciążenia serwera, skrócić czas oczekiwania i zminimalizować ryzyko błędów podczas ładowania.

Zacznijmy od prostych kroków, a potem przejdziemy do bardziej zaawansowanych i sprytnych trików.

Wyłączanie indeksów i triggerów

Indeksy i triggery to świetne rzeczy, które sprawiają, że nasze bazy danych są mądre i responsywne. Ale podczas masowego ładowania danych mogą mocno spowolnić proces, bo serwer próbuje aktualizować indeksy i odpalać triggery dla każdego wiersza, który wrzucasz.

Żeby tymczasowo odciążyć system, możesz je wyłączyć.

Przykład wyłączania indeksów i triggerów:

-- Wyłączamy triggery dla tabeli
ALTER TABLE students DISABLE TRIGGER ALL;

-- Ładujemy dane
COPY students FROM '/path/to/students.csv' DELIMITER ',' CSV HEADER;

-- Włączamy triggery z powrotem
ALTER TABLE students ENABLE TRIGGER ALL;

Jak to działa?

  1. Tymczasowo wyłączamy wszystkie triggery komendą DISABLE TRIGGER ALL.
  2. Po załadowaniu danych włączamy triggery z powrotem przez ENABLE TRIGGER ALL.

Typowy błąd: jeśli zapomnisz włączyć triggery z powrotem, niektóre procesy automatyzacji (np. aktualizacja pól domyślnych) mogą nie działać poprawnie. Więc nie zapomnij przywrócić wszystko na miejsce — to jak wyjście z trybu "samolotowego" w telefonie.

Użycie transakcji

Transakcje pozwalają załadować wszystkie dane naraz, jakby to była jedna wielka operacja. Jeśli coś pójdzie nie tak, możesz cofnąć zmiany i twoja baza nie zamieni się w bałagan z kawałków danych.

Przykład użycia transakcji:

-- Zaczynamy transakcję
BEGIN;

-- Ładujemy dane
COPY courses FROM '/path/to/courses.csv' DELIMITER ',' CSV HEADER;

-- Zatwierdzamy zmiany
COMMIT;

Dlaczego to działa szybciej?

Kiedy ładujesz dane bez transakcji, serwer zatwierdza zmiany po każdym wierszu. Z transakcją robi to tylko raz na końcu ładowania, co oszczędza mnóstwo czasu.

Wyłączanie sprawdzania integralności

Jeśli nie musisz sprawdzać kluczy obcych albo ograniczeń unikalności podczas ładowania, wyłącz je. W przeciwnym razie baza będzie sprawdzać każdy wiersz, co spowalnia proces.

Przykład wyłączania sprawdzania integralności:

SET session_replication_role = 'replica';

-- Ładujemy dane
COPY enrollments FROM '/path/to/enrollments.csv' DELIMITER ',' CSV HEADER;

SET session_replication_role = 'origin';

session_replication_role = 'replica' wyłącza sprawdzanie integralności danych (np. unikalność i ograniczenia FOREIGN KEY).

Zwiększanie pamięci dla operacji

Ustawienia pamięci PostgreSQL mogą poprawić wydajność ładowania danych. Kluczowe parametry to work_mem i maintenance_work_mem.

Przykład zwiększenia pamięci:

-- Zwiększamy ilość pamięci
SET work_mem = '64MB';
SET maintenance_work_mem = '256MB';

-- Ładujemy dane
COPY teachers FROM '/path/to/teachers.csv' DELIMITER ',' CSV HEADER;

Co to daje?

  • work_mem jest używany do operacji pośrednich, takich jak sortowanie czy haszowanie.
  • maintenance_work_mem wpływa na operacje związane z indeksami, np. ich przebudowę.

Porada: Uważaj ze zwiększaniem pamięci, szczególnie na systemach z ograniczonymi zasobami.

Przygotowanie danych przed ładowaniem

Przygotowanie danych może mocno skrócić czas ładowania. Na przykład, jeśli masz duplikaty w wierszach, przefiltruj je wcześniej, żeby PostgreSQL nie tracił czasu na niepotrzebne dane.

Przykład czyszczenia danych:

Jeśli masz plik z powtarzającymi się wierszami, możesz użyć Pythona, żeby je usunąć.

import pandas as pd

# Ładujemy plik CSV
data = pd.read_csv('students.csv')

# Usuwamy duplikaty
data = data.drop_duplicates()

# Zapisujemy czysty CSV
data.to_csv('students_clean.csv', index=False)

Partyckjonowanie danych

Jeśli masz ogromny plik, podziel go na kilka mniejszych. Dzięki temu PostgreSQL sprawniej przetworzy dane.

Przykład:

Podziel plik large_data.csv na kawałki po 1000 wierszy za pomocą Linuxa:

split -l 1000 large_data.csv chunk_

Potem ładuj je osobno:

COPY students FROM 'chunk_aa' DELIMITER ',' CSV HEADER;
COPY students FROM 'chunk_ab' DELIMITER ',' CSV HEADER;
-- I tak dalej

Ładowanie w tle

Jeśli masz taką możliwość, możesz użyć procesów w tle do ładowania danych, żeby nie przeciążać głównej bazy.

Narzędzia takie jak pg_cron pozwalają uruchamiać zadania według harmonogramu.

Przykład: ustawienie ładowania w tle z pg_cron:

CREATE EXTENSION pg_cron;

SELECT cron.schedule('*/5 * * * *', $$COPY students FROM '/path/to/data.csv' DELIMITER ',' CSV HEADER$$);

Co 5 minut dane z pliku będą ładowane do tabeli.

To tylko przykład, w praktyce tak się nie robi! Chciałem tylko pokazać, że PostgreSQL jest mega elastyczny i możesz bardzo elastycznie zarządzać dodawaniem danych prosto z SQL-skryptów.

Pułapki

Kilka rzeczy, na które warto uważać:

  • Jeśli wyłączasz indeksy i triggery, nie zapomnij ich włączyć z powrotem! Zapomnisz — będziesz naprawiać błędy po ładowaniu.
  • Zwiększając parametry pamięci, pilnuj zasobów serwera: jeden łakomy request może zjeść całą RAMkę.
  • Przy użyciu transakcji upewnij się, że plik danych nie ma krytycznych błędów. Jeden błąd wystarczy, żeby cofnąć całe ładowanie.

Rekomendacje na przyszłość

Teraz już wiesz, jak optymalizować masowe ładowanie danych — od wyłączania indeksów po użycie transakcji. Te umiejętności pomogą ci nie tylko szybciej ładować dane, ale też oszczędzą zasoby serwera, nerwy, kawę i sprawią, że użytkownicy będą zadowoleni.

Następnym razem, gdy będziesz pracować z plikami o rozmiarze gigabajtów, będziesz gotowy!

2
Zadanie
SQL SELF, poziom 24, lekcja 3
Niedostępne
Wyłączenie sprawdzania integralności danych
Wyłączenie sprawdzania integralności danych
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION