„Polars“, „DuckDB“ ar „pandas“: 50 mln. eilučių pakeičia pasirinkimą

|Autorius: QUASA redakcija|5 min. skaitymo
„Polars“, „DuckDB“ ar „pandas“: 50 mln. eilučių pakeičia pasirinkimą

„Uvik Software“ 50 mln. eilučių grupavimo bandyme su 5,84 GiB atminties riba „DuckDB“ užbaigė visas dešimt užklausų, „Polars“ – devynias, o „pandas“ sustojo kraudama duomenis. To paties bandymo mažesniame, 10 mln. eilučių, rinkinyje visos trys bibliotekos veikė, todėl svarbesnis tapo konkrečių užklausų greitis: grupavimo laikų suma buvo 2,86 s su „Polars“, 3,91 s su „DuckDB“ ir 16,39 s su „pandas“.

Jei rinkinys telpa į atmintį ir analizė jau parašyta su „pandas“, vien jo dydis nėra pakankama priežastis keisti įrankį. Naujai duomenų rėmelių transformacijų grandinei, ypač kai reikia sujungti lenteles, šiame bandyme palankiausias buvo „Polars“. Kai atminties atsarga maža arba norima SQL užklausomis apdoroti failus jų iš anksto nekraunant į duomenų rėmelį, stiprėja „DuckDB“ argumentas. Tai pasirinkimas pagal darbo eigą ir užklausą, o ne pastovi bibliotekų greičio eilė.

Ką pakeičia rinkinio dydis

Mažesniame scenarijuje galima lyginti užbaigtų operacijų trukmę. Didesniame pirmiausia tenka klausti, ar pavyksta įkelti duomenis ir užbaigti sunkiausią grupavimą neviršijus atminties ribos. Todėl greičiausias mažesnės lentelės rezultatas savaime negarantuoja, kad tas pats variklis bus tinkamiausias gerokai didesnei lentelei.

  • Duomenys telpa į atmintį, o svarbiausi sujungimai: bandytų sujungimų serijoje pirmavo „Polars“. Ši išvada taikoma sujungimams, kurių išvestis buvo visiškai sukurta, o ne bet kuriai užklausai su JOIN.
  • Duomenys telpa į atmintį, o svarbiausias grupavimas: „Polars“ laimėjo pagal visų bandytų grupavimo užklausų laikų sumą, tačiau atskiras užklausas dažniau laimėjo „DuckDB“. Lemiamas skirtumas buvo grupių skaičius ir skaičiavimo pobūdis.
  • Duomenys artėja prie atminties ribos: šiame didžiojo rinkinio bandyme visas užklausas įvykdė „DuckDB“. „Polars“ atliko daugumą, bet sustojo, kai grupavimas sukūrė itin didelį rezultatą; „pandas“ iki užklausų vykdymo nepriėjo.

Šias baigtis riboja metodika. Naudoti sintetiniai duomenys, nedidelė mašina ir atskiri kiekvieno variklio procesai. Mažesnio rinkinio laikai yra atskirų užklausų pakartojimų medianų suma, o didysis bandymas vykdytas vieną kartą. Įkėlimas matuotas atskirai nuo užklausų, todėl pateikti grupavimo laikai neapima viso kelio nuo failo iki rezultato.

Grupavimas ir sujungimai: užklausa gali pakeisti nugalėtoją

„Polars“, „DuckDB“ ir „pandas“ sujungia lenteles pagal tuos pačius raktus; bandytus sujungimus greičiausiai užbaigia „Polars“.

Grupavimo laikų suma slepia skirtingas apkrovas. Mažai grupių sudarančių raktų agregacijose ir kai kuriuose statistiniuose skaičiavimuose greičiau veikė „DuckDB“. Kai raktai sukūrė daug skirtingų grupių, dažniau pirmavo „Polars“. Vieno stulpelio sumos matavimas todėl menkai apibūdina užklausą, kuri grupuoja pagal kelis raktus arba skaičiuoja koreliaciją.

Bandytuose lentelių sujungimuose „Polars“ laimėjo kiekvieną užklausą. Čia svarbi išvesties forma: „DuckDB“ pagal bandymo taisykles rezultatą įrašydavo į naują lentelę. Jeigu darbo eigoje po JOIN reikia tik kelių agreguotų reikšmių, didelės tarpinės lentelės kurti gali nereikėti. Atskirame atkuriamame sujungimo ir agregavimo bandyme greičiausias buvo „DuckDB“; ten matuota kita užklausa, kitos bibliotekų versijos ir kita mašina. Šie rezultatai aprašo skirtingus darbus, todėl jų laikų negalima sudėti į bendrą reitingą.

Vienos „pandas“ grupavimo užklausos vykdymą smarkiai veikė Python funkcija, kviečiama kiekvienai grupei. Vektorizuota išraiška galėtų pakeisti jos trukmę, nors aptariamas bandymas tokio varianto nematavo. Lyginant jau turimą analizės kodą, verta skirti variklio ribą nuo konkretaus užklausos užrašymo būdo.

CSV, „Parquet“ ir įkėlimo kaina

To paties rinkinio CSV ir „Parquet“ failai skiriasi dydžiu; bandyme „Polars“ greičiau įkėlė „Parquet“.

Mažesnio grupavimo rinkinio CSV failas bandyme užėmė 569 MB, o tų pačių duomenų „Parquet“ failas – 213 MB. „Polars“ jį įkėlė atitinkamai per 2,39 ir 0,93 s; „Parquet“ įkėlimas taip pat buvo greitesnis su „pandas“ ir „DuckDB“. Šie laikai apima pasirinktą įkėlimo procedūrą, įskaitant duomenų tipų keitimą, o „DuckDB“ atveju ir kopijavimą į vidinę lentelę. Jie nematuoja tiesioginės SQL užklausos į failą.

„Polars“ atidėtųjų užklausų vadovas aprašo, kaip užklausą pradėti nuo „scan_csv“ arba atitinkamo „Parquet“ nuskaitymo. Užklausa sudaroma prieš vykdymą, tad optimizatorius gali mažinti iš failo skaitomų duomenų kiekį. Tai aktualu, kai iš didelio rinkinio reikia tik pasirinktų stulpelių ir filtruotų eilučių, o ne viso įkelto duomenų rėmelio.

CSV tekste stulpelių reikšmes reikia interpretuoti ir priskirti joms tipus. Stulpelinis „Parquet“ formatas ypač naudingas kartotinėms analizėms, kurios skaito tik dalį stulpelių. Vis dėlto mažesnis failas diske nereiškia tiek pat mažesnio atminties poreikio vykdant grupavimą: atmintį naudoja ir iškoduoti duomenys, ir tarpiniai bei galutiniai rezultatai.

Atminties ribą lemia ir tarpinis rezultatas

Didžiajame bandyme „Polars“ įkėlė „Parquet“ rinkinį ir įvykdė daugumą grupavimo užklausų, bet sustojo ties užklausa, kuri sudarė itin daug skirtingų grupių. „DuckDB“ ją užbaigė. Tai parodo skirtumą tarp klausimų „ar telpa pradinis rinkinys?“ ir „ar telpa visa užklausa?“: agregavimo struktūra gali augti net tada, kai pradinis failas sėkmingai nuskaitytas.

Oficialus „pandas“ darbo su dideliais rinkiniais vadovas siūlo mažinti skaitomų stulpelių skaičių, parinkti taupesnius duomenų tipus ir, kai operacija leidžia, apdoroti duomenis dalimis. Dalijimas veiksmingas tada, kai tarp dalių reikia mažai derinimo. Sudėtingi sujungimai ar agregacijos pagal daugelį raktų reikalauja papildomos būsenos, todėl vien dalinis skaitymas jų atminties problemos automatiškai neišsprendžia.

Suspausto failo dydis dėl to yra prastas vienintelis atminties matas. Svarbesnis didžiausias viso proceso naudojimas vykdant būtent tą užklausą, kurios rezultato reikia. Ribotos atminties aplinkoje galimybė ją užbaigti nusveria kelių sekundžių pranašumą lengvesniame bandyme.

SQL ir duomenų rėmelių darbo eigos

„DuckDB“ vykdo SQL užklausą tiesiai su „Parquet“ duomenimis ir perduoda sumažintą rezultatą į „pandas“.

„DuckDB“ tinka, kai analizę patogu išreikšti SQL: filtruoti, jungti ir grupuoti duomenis, o į Python grąžinti tik reikalingą rezultatą. „DuckDB“ techninis aprašymas nurodo, kad lygiagrečias užklausas galima vykdyti tiesiogiai su „Parquet“ failais ir esamais „pandas“ duomenų rėmeliais, prieš tai jų neimportuojant į atskirą duomenų bazės lentelę. Taigi esamas „pandas“ kodas gali priimti jau sumažintą SQL užklausos rezultatą.

„Polars“ labiau atitinka darbo eigą, kurioje filtrai, stulpelių išraiškos, sujungimai ir agregacijos sudaro vieną atidėtą duomenų rėmelių užklausą. „pandas“ lieka patogus, kai duomenys bei tarpiniai rezultatai telpa į atmintį ir tolesni įrankiai laukia būtent jo duomenų rėmelio. Sprendimą todėl verta grįsti visa reikalinga operacijų grandine: failo nuskaitymu, skaičiavimu, atminties piku ir galutinės išvesties forma.

Taip pat skaitykite:

Dalintis:

Prenumeruokite mūsų naujienlaiškį

Gaukite naujausias Web3, DI ir kriptovaliutų naujienas tiesiai į savo el. pašto dėžutę.

0