Kas yra QuestDB ir kodėl verta apie jį žinoti
Laiko eilučių duomenų bazės – tai ne naujiena IT pasaulyje, bet QuestDB į šią perpildytą rinką atėjo su gana drąsiu teiginiu: mes esame greičiausi. Ir žinote ką? Jie turi tam pagrindo. Šis atvirojo kodo projektas, parašytas Java ir C++ kalbomis, orientuotas į maksimalų našumą dirbant su laiko eilučių duomenimis. Jei jūsų aplikacija renka metrikas, sensorių duomenis, finansinius tickus ar bet kokią kitą informaciją, kur svarbus laiko žymės komponentas – QuestDB tikrai vertas dėmesio.
Pirmą kartą susidūręs su QuestDB, buvau skeptiškas. Dar viena duomenų bazė? Rimtai? Bet kai pamatai, kaip ji apdoroja milijonus įrašų per sekundę su minimaliais resursais, pradedi suprasti, kad čia ne tik marketingas. Projektas pradėtas 2014 metais, o nuo 2019-ųjų tapo atviro kodo sprendimu su Apache 2.0 licencija.
Kas ypač įdomu – QuestDB palaiko SQL sintaksę su laiko eilučių specifiniais praplėtimais. Tai reiškia, kad jums nereikia mokytis visiškai naujos užklausų kalbos, kaip tai būtų su kai kuriomis kitomis time-series DB. Galite pradėti dirbti beveik iš karto, jei esate susipažinę su SQL.
Architektūra ir technologiniai sprendimai
QuestDB architektūra yra tai, kas iš tiesų daro jį greitą. Čia nėra jokios magijos – tik protingi inžineriniai sprendimai. Duomenų bazė naudoja column-oriented saugojimo modelį, kuris idealiai tinka analitinėms užklausoms. Kai jums reikia apskaičiuoti vidutinę temperatūrą per paskutinę valandą, sistema skaito tik temperatūros stulpelį, o ne visus įrašus.
Vienas iš svarbiausių QuestDB bruožų – tai kaip jie dirba su laiko particionavimu. Duomenys automatiškai skirstomi pagal laiko intervalus (diena, mėnuo, metai), ir tai leidžia neįtikėtinai greitai atlikti užklausas konkretiems laikotarpiams. Pavyzdžiui, jei jums reikia duomenų iš praėjusios savaitės, sistema tiesiog ignoruoja visas kitas particijas.
Įrašymo našumas pasiekiamas naudojant append-only modelį ir memory-mapped failus. Nauji duomenys rašomi tiesiogiai į atmintį, o operacinė sistema pati pasirūpina jų išsaugojimu į diską. Tai eliminuoja daug I/O operacijų ir leidžia pasiekti milijonus įrašų per sekundę viename branduolyje.
SIMD instrukcijos (Single Instruction, Multiple Data) yra dar vienas paslaptis. QuestDB natyviai naudoja šias procesoriaus galimybes, kad atliktų operacijas su keliais duomenimis vienu metu. Tai ypač efektyvu atliekant agregacijas ar skaičiavimus.
Kaip pradėti dirbti su QuestDB
Diegimas yra paprastas kaip du pirštai. Galite naudoti Docker, tiesiog parsisiųsti binary failą arba kompiliuoti iš šaltinio. Aš paprastai rekomenduoju Docker variantą testavimui:
docker run -p 9000:9000 -p 9009:9009 -p 8812:8812 questdb/questdb
Po kelių sekundžių turite veikiančią QuestDB instanciją. Portas 9000 – tai web konsolė, kur galite rašyti SQL užklausas ir matyti rezultatus realiuoju laiku. 9009 portas skirtas InfluxDB line protocol (labai greitas būdas įkelti duomenis), o 8812 – PostgreSQL wire protocol.
Taip, teisingai supratote – QuestDB palaiko PostgreSQL protokolą. Tai reiškia, kad galite naudoti bet kurį Postgres klientą ar biblioteką. Psycopg2 Python’e? Veikia. Node.js pg biblioteka? Be problemų. Tai labai sumažina įėjimo barjerą.
Pirmoji lentelė galėtų atrodyti taip:
CREATE TABLE sensors (
sensor_id SYMBOL,
temperature DOUBLE,
humidity DOUBLE,
timestamp TIMESTAMP
) timestamp(timestamp) PARTITION BY DAY;
Atkreipkite dėmesį į SYMBOL tipą – tai QuestDB optimizacija kartojamoms string reikšmėms. Vietoj to, kad saugotų „sensor_001” tūkstančius kartų, sistema saugo tik nuorodą į žodyną. Tai sutaupo daug vietos ir pagreitina užklausas.
Duomenų įkėlimas: greitis yra svarbu
Yra keletas būdų įkelti duomenis į QuestDB, ir jų našumas labai skiriasi. SQL INSERT sakiniai veikia, bet jie nėra greičiausi. Jei jums reikia maksimalaus našumo, turėtumėte naudoti vieną iš šių metodų:
InfluxDB Line Protocol per TCP yra greičiausias būdas. Galite siųsti duomenis tokiu formatu:
sensors,sensor_id=001 temperature=23.5,humidity=45.2 1638360000000000000
Šis metodas leidžia pasiekti milijonus įrašų per sekundę. Nereikia jokių transakcijų, commit’ų ar kitų papildomų veiksmų. Tiesiog siunčiate duomenis, ir jie atsiranda duomenų bazėje.
PostgreSQL wire protocol yra patogus, kai jau turite esamą kodą su Postgres. Našumas šiek tiek mažesnis nei su ILP, bet vis tiek labai geras. Galite naudoti prepared statements ir batch insert’us.
REST API taip pat egzistuoja, bet jis lėčiausias iš visų variantų. Tinka nedideliems duomenų kiekiams ar retkarčiams įkėlimams.
Praktinis patarimas: jei renkatės tarp metodų, pradėkite nuo to, kuris jums patogiausias. Optimizuoti galėsite vėliau, kai suprasite, ar našumas yra problema. Daugeliu atvejų net REST API bus pakankamai greitas.
SQL užklausos su laiko eilučių priedais
QuestDB SQL sintaksė yra beveik standartinė, bet su keliais naudingais praplėtimais. SAMPLE BY funkcionalumas leidžia lengvai agregatuoti duomenis pagal laiko intervalus:
SELECT timestamp, avg(temperature), max(humidity)
FROM sensors
WHERE timestamp > dateadd('d', -7, now())
SAMPLE BY 1h;
Ši užklausa grąžins vidutinę temperatūrą ir maksimalią drėgmę kas valandą per paskutines 7 dienas. Be SAMPLE BY turėtumėte rašyti sudėtingą GROUP BY su laiko funkcijomis.
LATEST ON yra dar vienas naudingas praplėtimas. Jis leidžia gauti naujausius duomenis kiekvienam unikaliam raktui:
SELECT * FROM sensors
LATEST ON timestamp PARTITION BY sensor_id;
Tai grąžins naujausią įrašą kiekvienam sensoriui. Standartiniame SQL tam reikėtų subquery ar window funkcijų, kurios būtų lėtesnės.
ASOF JOIN – tai funkcionalumas, kurio tikrai trūksta standartiniame SQL. Jis leidžia sujungti duomenis pagal artimiausią laiko žymę:
SELECT * FROM prices
ASOF JOIN volumes ON symbol;
Tai ypač naudinga finansinėse aplikacijose, kur skirtingi duomenų srautai ateina skirtingais intervalais, bet jums reikia juos sujungti pagal laiką.
Našumo optimizavimas ir best practices
Net ir su greita duomenų baze galite pasiekti blogą našumą, jei nesilaikote tam tikrų principų. Štai ką išmokau per metus darbo su QuestDB:
Particionavimas yra kritiškai svarbus. Pasirinkite tinkamą particionavimo intervalą pagal jūsų duomenų kiekį ir užklausų pobūdį. Jei renkate duomenis kas sekundę ir saugote metus, dienos particijos bus optimalios. Jei duomenų mažai, mėnesio particijos gali būti geresnės.
SYMBOL tipas turėtų būti naudojamas visiems stulpeliams su ribotos kardinalumo string reikšmėmis. Šalių kodai, sensorių ID, produktų kategorijos – visi jie turėtų būti SYMBOL, ne STRING. Tai gali pagreitinti užklausas 10-100 kartų.
Indexed stulpeliai QuestDB veikia kitaip nei tradicinėse duomenų bazėse. Čia indeksai kuriami tik SYMBOL stulpeliams, ir jie nėra B-tree, o hash-based. Tai reiškia, kad jie puikiai tinka equality užklausoms (WHERE sensor_id = ‘001’), bet netinka range užklausoms.
Vienas dalykas, kuris mane nustebino – QuestDB neturi secondary indexes laiko stulpeliui. Jums nereikia kurti indekso timestamp stulpeliui, nes jis automatiškai optimizuotas. Tai supaprastina duomenų bazės valdymą.
Deduplication QuestDB neturi automatinio. Jei įkelsite tą patį įrašą du kartus, turėsite du įrašus. Tai yra sąmoningas dizaino sprendimas dėl našumo. Jei jums reikia deduplication, turite jį implementuoti aplikacijos lygmenyje arba naudoti DISTINCT užklausose.
Integracijos su kitomis sistemomis
QuestDB nebandė išradinėti rato ir puikiai integruojasi su populiariais įrankiais. Grafana turi oficialų QuestDB data source pluginą. Galite kurti dashboardus su real-time metrikomis per kelias minutes. Tai vienas iš paprasčiausių būdų vizualizuoti QuestDB duomenis.
Kafka integracija yra natūrali – galite naudoti Kafka Connect su JDBC connector arba rašyti duomenis tiesiogiai per InfluxDB line protocol. Daugelis mūsų klientų naudoja Kafka kaip duomenų srautų šaltinį, o QuestDB kaip ilgalaikį saugyklą ir analitikos platformą.
Prometheus metrikas galite eksportuoti į QuestDB naudojant remote write funkciją. Tai leidžia saugoti metrikas ilgiau nei Prometheus lokaliai, ir atlikti sudėtingesnes analizes SQL užklausomis.
Python ekosistema puikiai veikia su QuestDB. Pandas DataFrame galite įkelti tiesiogiai naudojant psycopg2 ar QuestDB Python biblioteką. Tai ypač patogu data science projektams, kur reikia greitai eksperimentuoti su laiko eilučių duomenimis.
Vienas mano mėgstamiausių use case’ų – naudoti QuestDB kaip backend’ą Jupyter notebook’uose. Galite analizuoti milijonus įrašų interaktyviai, o užklausos grįžta per sekundes. Tai daug geriau nei bandyti viską laikyti Pandas DataFrame’uose atmintyje.
Monitoringas ir troubleshooting
QuestDB turi įtaisytą web konsolę, kuri yra ne tik SQL editor’ius, bet ir monitoring įrankis. Galite matyti aktyvias užklausas, sistemos metrikas, lentelių dydžius ir kitus svarbius parametrus. Tai nėra Grafana, bet kasdieniniam darbui visiškai pakanka.
Log failai yra jūsų draugas, kai kažkas negerai. QuestDB logina visas klaidas ir warnings į stdout ir į failą. Jei užklausa veikia lėtai, pažiūrėkite į logus – dažnai rasite užuominą, kas ne taip.
Sistemos lentelės leidžia užklausti metaduomenis apie duomenų bazę. Pavyzdžiui:
SELECT * FROM tables();
Tai grąžins visas lenteles su jų dydžiais ir kitais parametrais. Yra ir daugiau tokių funkcijų – columns(), table_columns(), ir kitos.
Viena dažna problema, su kuria susidūriau – out of memory klaidos. QuestDB naudoja daug atminties, ypač kai atlieka sudėtingas agregacijas. Jei matote tokias klaidas, padidinkite heap size arba optimizuokite užklausas, kad jos apdorotų mažiau duomenų vienu metu.
Backup ir recovery QuestDB yra paprastas – tiesiog nukopijuokite db direktoriją. Duomenų bazė saugo viską failų sistemoje, ir nėra jokių hidden state’ų. Tai vienas iš privalumų embedded duomenų bazės dizaino.
Kada rinktis QuestDB ir kada ne
QuestDB nėra universalus sprendimas visoms problemoms. Jis puikiai tinka konkretiems use case’ams, bet yra situacijų, kur geriau rinktis ką nors kita.
Kada QuestDB yra puikus pasirinkimas: IoT aplikacijos su milijonais sensorių, finansiniai duomenys su high-frequency trading, aplikacijų monitoringas ir metrikos, log agregacija ir analizė, bet koks real-time analytics su laiko komponentu. Jei jūsų duomenys auga greitai, jums reikia greitų užklausų, ir laiko komponentas yra svarbus – QuestDB bus puikus.
Kada turėtumėte apsvarstyti alternatyvas: Jei jums reikia transakcijų su ACID garantijomis visame duomenų rinkinyje. QuestDB palaiko atomines operacijas particionų lygmenyje, bet ne distributed transakcijas. Jei jūsų duomenys neturi laiko komponento arba jis nėra svarbus – tiesiog naudokite PostgreSQL ar kitą reliacinę duomenų bazę.
Jei jums reikia sudėtingų ryšių tarp duomenų ir daug JOIN operacijų – graph duomenų bazė ar tradicinė RDBMS bus geresnė. QuestDB palaiko JOIN’us, bet jis optimizuotas agregacijoms, ne sudėtingiems ryšiams.
Jei jums reikia full-text search – geriau naudoti Elasticsearch ar panašius sprendimus. QuestDB turi bazinę string paieškos funkciją, bet ji nėra jo stiprioji pusė.
Ką ateitis žada QuestDB
Projektas aktyviai vystomas, ir roadmap atrodo įdomiai. Komanda dirba prie replication ir clustering funkcionalumo, kas leistų horizontaliai skalėti QuestDB. Dabar galite skalėti tik vertikaliai (didesnis serveris), bet ateityje galėsite turėti klasterį.
Planuojama geresnė integracija su cloud platformomis. Jau dabar galite paleisti QuestDB AWS, GCP ar Azure, bet komanda dirba prie managed service, kuris supaprastintų deployment’ą ir valdymą.
Dar viena įdomi kryptis – geresnė streaming integracija. QuestDB jau dabar puikiai veikia su Kafka, bet planuojama native integracija su kitais streaming platformomis ir real-time processing galimybės pačioje duomenų bazėje.
Bendruomenė auga, ir tai geras ženklas. Vis daugiau įmonių naudoja QuestDB production’e, ir tai reiškia, kad projektas brandėja. GitHub’e matau aktyvią diskusiją, bug’ai ištaisomi greitai, ir nauji feature’ai atsiranda reguliariai.
Asmeniškai manau, kad QuestDB turi gerą šansą tapti vienu iš pagrindinių time-series duomenų bazių pasirinkimų. Jie turi tinkamą balansą tarp našumo, paprastumo ir funkcionalumo. Tai nėra dar vienas hype projektas – tai solidus įrankis, sprendžiantis realias problemas.
Jei dar neišbandėte QuestDB, rekomenduoju skirti valandą ar dvi eksperimentams. Parsisiųskite Docker image’ą, įkelkite keletą milijonų įrašų, pabandykite įvairias užklausas. Greičiausiai būsite maloniai nustebinti, kaip greitai viskas veikia ir kaip paprasta pradėti. O jei jau naudojate kitą time-series duomenų bazę ir esate patenkinti – puiku, bet žinokite, kad yra alternatyvų, kurios gali būti greitesnės ir pigesnės.
