Jest sprawa, sa dwa wielkie pliki CSV i, wedle jakiejś logiki, trzeba brakujące rekordy z jednego pliku uzupełnić drugim, i, uzupełniony plik, zwrócić. Jak to zrobić efektywnie, jest to w Pythonie, ale to bez znaczenia, bo jak coś się znajdzie w czyms innym to się serwis zrobi. Będę inwestygował, nawet se już zdzirę zrobiłem:), ale jak ktoś coś już ma, rozwiązał podobne, to chętnie skorzystam;)
Przetwarzanie Dużych Plików CSV
- Rejestracja: dni
- Ostatnio: dni
- Postów: 3889
Sprecyzuje co masz na myśli pisząc duże pliki csv
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
Tak ~ kilka milionów liniii każdy, nie wiem dokładnie.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 1620
Kilka milionów linii po kilkaset znaków to jeszcze nie powinien być problem — może i już się nie mieści w cache’u, ale tak prawie. Prawie na pewno wystarczy podejście „na pałę” — wczytać pierwszy plik do setu, wczytać drugi plik do setu, zwrócić pierwszy | drugi, fajrant.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
Masz rację, może tak być, tylko nie wiem czy logika tego uzupełniania pozwoli, zobacze na to jutro.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 6962
Jaką chcesz logikę?
Doklejasz jeden plik do drugiego, sortujesz linie i sprawdzasz je po kolei, czy poprzednia linia == obecna linia. Jeśli tak, to usuwasz obecną.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
Dobra, jednak drugi plik, ten w którym szukamy, (szukanie jest prostsze niż myślałem - odwzorowuje logikę left join) będzie wielki, kilkadziesiąt GB, może i ponad 100.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 6962
ChatGPT radzi, żeby przerzucić te pliki CSV do bazy danych: https://chatgpt.com/share/682da7ad-3c60-800a-848e-4e8c8ade88f9
Wtedy będziesz mógł na tych wielkich plikach wykonywać zapytania.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 145
- Rejestracja: dni
- Ostatnio: dni
Jak wyglądają dane w plikach? Posortowane? Kolejność taka sama w obu? Losowa?
Skąd wiadomo, że jakichś danych brakuje?
Jeśli nie posortowane (przynajmniej w jednym pliku), to prawdopodobnie będziesz musiał to zrobić. Potem 1) jedziesz linijka po linijce po drugim pliku i 2) przepisujesz do pliku docelowego, 3) szukasz binarnie (w plikach tekstowych też da się wyszukiwać binarnie) odpowiadającej linijki w pierwszym, posortowanym pliku, 4) jeśli linijki w drugim pliku brakuje na podstawie pewnych kryteriów, to dopisujesz linijkę do docelowego pliku z pliku pierwszego.
Zresztą narzędzia masz już gotowe i to nawet do nieposortowanych plików - grep, awk, diff itp. (-> https://stackoverflow.com/questions/21188905/how-to-find-which-line-is-missing-in-another-file).
- Rejestracja: dni
- Ostatnio: dni
- Postów: 158
ja bym spróbował zrobić unikalny klucz na podstawie wiersza z pierwszego pliku, może da się skrócić na tyle aby klucz zmieścił się w pamięci. Wtedy reszta będzie prosta, przeglądamy pierwszy plik, tworzymy klucz, zapisujemy jako hash (np. dict w Pythonie), przeglądamy drugi i dopisujemy brakujące wiersze. Raczej nie da się szybciej.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 1907
Może nie musisz ładować całego pliku do pamięci: https://www.baeldung.com/java-read-lines-large-file
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
Pewnie że nie muszę, a nawet nie mogę, zatanawiam się nad technologiami, jak polars, dask...
- Rejestracja: dni
- Ostatnio: dni
Ile rekordów jest w tych plikach konkretnie?
Ja bym przejechał pierwszy plik, przepisywał do wyjściowego i dla każdej linii liczył jakiś krótki checksum, długość checksuma w zależności od ilości rekordów 24 do 32 bitów tak żeby cała tablica się zmieściła w pamięci i w pamięci odhaczasz znalezione checksumy w tablicy bitów.
Potem jedziesz po drugim pliku i przepisujesz do wyjściowego pliku wszystkie linie których checksuma nie było wcześniej, a te które były zapamiętujesz
na końcu trzeci przejazd po pierwszym pliku żeby porównać rekordy bezpośrednio z tymi które miały kolizje.
Złożoność obliczeniowa O(n) i optymistycznie pamięciowa O(1)
Brzmi jak minuta roboty z chatgpt + kilkanaście minut działania skryptu.
Nawet nie musisz parsować tych plików jako csv tylko możesz potraktować jak stringi
- Rejestracja: dni
- Ostatnio: dni
- Postów: 149
Spine napisał(a):
Jaką chcesz logikę?
Doklejasz jeden plik do drugiego, sortujesz linie i sprawdzasz je po kolei, czypoprzednia linia==obecna linia. Jeśli tak, to usuwasz obecną.
Popieram, można np. tak:
cat file1 file2 > tmp_file
sort -u tmp_file > result
- Rejestracja: dni
- Ostatnio: dni
- Postów: 342
Duckdb zobacz. Wymienione przez ciebie polars, pandas itp też może dać radę.
Jak tak zapytać off top. Co za pojebane..... generuje Csv po 100gb i jak to zrobił.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
ŁF napisał(a):
Jak wyglądają dane w plikach? Posortowane? Kolejność taka sama w obu? Losowa?
Skąd wiadomo, że jakichś danych brakuje?Jeśli nie posortowane (przynajmniej w jednym pliku), to prawdopodobnie będziesz musiał to zrobić. Potem 1) jedziesz linijka po linijce po drugim pliku i 2) przepisujesz do pliku docelowego, 3) szukasz binarnie (w plikach tekstowych też da się wyszukiwać binarnie) odpowiadającej linijki w pierwszym, posortowanym pliku, 4) jeśli linijki w drugim pliku brakuje na podstawie pewnych kryteriów, to dopisujesz linijkę do docelowego pliku z pliku pierwszego.
Zresztą narzędzia masz już gotowe i to nawet do nieposortowanych plików - grep, awk, diff itp. (-> https://stackoverflow.com/questions/21188905/how-to-find-which-line-is-missing-in-another-file).
Nie są posortowane, tak wiem jakich brakuje bo pewna wartość w pierwszym (niewielkim pliku) jest specyficzna. W sumie to na razie jednak tego nie robię. A problem jest taki, że dla tych specyficznych wartości trzeba znaleźć inną wartość z ogromnego pliku. Wpadłem na pomysł, żeby batchami iterowac po tym wielkim i dodawac do słownika tylko te potrzebne, i chyba big data nie będą potzrebne, ale jak powyżej, na razie muszę to zostawić
- Rejestracja: dni
- Ostatnio: dni
- Postów: 1359
To może być potraktowane jako spam, bo to nie odpowiedź na pytanie, ale chciałbym tylko zarzucić taką myśli, że jeśli masz wpływ na to skąd i jakie biorą się te dane, to może warto się zastanowić czy aby na pewno powinny to być .csv, a nie na przykład .parquet, w razie gdybyś musiał regularnie dokonywać tych działań to warto jakoś zrównoleglać operacje np. sparkiem.
Taka tylko wolna myśl, chociaż pewnie to po prostu dwie .csvki i elo ^^, następny task
- Rejestracja: dni
- Ostatnio: dni
- Postów: 348
Spine napisał(a):
ChatGPT radzi, żeby przerzucić te pliki CSV do bazy danych: https://chatgpt.com/share/682da7ad-3c60-800a-848e-4e8c8ade88f9
Wtedy będziesz mógł na tych wielkich plikach wykonywać zapytania.
To jest właśnie zawsze moje podejście do tematu. Jak się pojawia jakiś temat przetwarzania plików (np. z innych systemów) to finalnie się okazuje, że to i tak w bazie potem ląduje. IMHO w sql ciężej mdyfikować/uzupełnić brakujące dane, w pythonie to chyba łatwiej się pisze (ale może wolniej działać).
- Rejestracja: dni
- Ostatnio: dni
- Postów: 750
Jeśli danych jest masa i nie mieści się w pamięci oraz dane są nieuporządkowane, i to co chcesz wykonać brzmi jak opis działania na tabelach baz danych, to wrzucenie tego do bazy danych wydaje się racjonalne. Jakby nie patrzeć alternatywą jest implementowanie dość typowo bazodanowych elementów. Zaoszczędzony czas możesz poświęcić na czytanie literatury o budowie systemów zarządzania bazami danych. Trochę tego jest. Tak książek jak i publikacji w mniejszych formatach.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 1019
Ważne są wymagania wydajnościowe. Jak to ma być zrobione raz/od czasu do czasu to szczerze mówiąc wszystko będzie ok. Python może i będzie 100x wolniejszy niż optymalne rozwiązanie, ale who cares.
Jak lubisz SQL to DuckDB. Jak nie to po prostu poproś czat GPT, żeby napisał to w jakimś wydajnym języku i elo
Jedynym problemem może być użycie pamięci więc warto poprosić czata o rozwiązanie strumieniowe, jeśli tak się da
Nie szedłbym w żadne "smart" rozwiązania, bo ktoś to musi utrzymywać. Duck jest fajny, bo każdy zna SQLa. Zwykły kod jest fajny, bo implementacja szczegółowej logiki jest prostsza niż konfiguracja jakiegoś "smart" rozwiązania
- Rejestracja: dni
- Ostatnio: dni
- Postów: 5023
Dzięki, yhm, DuckDB, spoko, może niedługo do tego wrócę, to zobaczę.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: warszawa
- Postów: 315
Nie są posortowane, tak wiem jakich brakuje bo pewna wartość w pierwszym (niewielkim pliku) jest specyficzna. W sumie to na razie jednak tego nie robię. A problem jest taki, że dla tych specyficznych wartości trzeba znaleźć inną wartość z ogromnego pliku. Wpadłem na pomysł, żeby batchami iterowac po tym wielkim i dodawac do słownika tylko te potrzebne, i chyba big data nie będą potzrebne, ale jak powyżej, na razie muszę to zostawić
Jak jeden plik jest malutki to mozesz załadowac go sobie całego do pamieci, i tak jak mówisz wczytywac "linia po linii" ten wielki plik. To powinno byc optymalne rozwiazanie, O(n) i najwiekszy wąskim gardłem bedzie odpowiednio sprawne wczytywanie duze pliku