KDB+ adatbázis: a pénzügyektől a Forma-1-ig

KDB+, cég terméke KX egy szűk körben széles körben ismert, rendkívül gyors, oszlopos adatbázis, amely idősorok tárolására és az ezek alapján végzett analitikus számítások tárolására szolgál. Kezdetben nagyon népszerű volt (és az is) a pénzügyi szektorban – az összes top 10 befektetési bank és számos jól ismert fedezeti alap, tőzsde és egyéb szervezet használja. A közelmúltban a KX úgy döntött, hogy bővíti ügyfélkörét, és most más területeken is kínál megoldásokat, ahol nagy mennyiségű adat van, idő szerint vagy más módon rendezve - telekommunikáció, bioinformatika, gyártás stb. Partnerei lettek az Aston Martin Red Bull Racing csapatának is a Forma-1-ben, ahol segítenek összegyűjteni és feldolgozni az autók szenzoraiból származó adatokat, valamint elemzik a szélcsatornás teszteket. Ebben a cikkben szeretném elmondani, hogy a KDB+ mely funkciói teszik kiemelkedően teljesítővé, miért hajlandók a cégek sok pénzt költeni rá, és végül, miért nem egy adatbázis.
 
KDB+ adatbázis: a pénzügyektől a Forma-1-ig
 
Ebben a cikkben megpróbálom általánosságban elmondani, mi az a KDB+, milyen képességekkel és korlátokkal rendelkezik, és milyen előnyei vannak a nagy mennyiségű adatot feldolgozni kívánó vállalatok számára. Nem megyek bele a KDB+ megvalósításának részleteibe, illetve a Q programozási nyelvének részleteibe, mindkét téma nagyon tág és külön cikket érdemel. Ezekről a témákról sok információ található a code.kx.com webhelyen, beleértve a Q - Q For Halandóknak című könyvet (lásd az alábbi linket).

Néhány kifejezés

  • Memórián belüli adatbázis. Adatbázis, amely a RAM-ban tárolja az adatokat a gyorsabb hozzáférés érdekében. Egy ilyen adatbázis előnyei egyértelműek, de a hátránya az adatvesztés lehetősége és a sok memória szükségessége a szerveren.
  • Oszlopos adatbázis. Olyan adatbázis, amelyben az adatokat oszloponként tárolják, nem pedig rekordonként. Egy ilyen adatbázis fő előnye, hogy egy oszlopból származó adatok együtt kerülnek tárolásra a lemezen és a memóriában, ami jelentősen felgyorsítja a hozzáférést. Nincs szükség a lekérdezésben nem használt oszlopok betöltésére. A fő hátrány az, hogy nehéz módosítani és törölni a rekordokat.
  • Idősorok. Adatok dátum vagy idő oszloppal. Az ilyen adatoknál jellemzően fontos az idő szerinti sorrend, hogy könnyen meg lehessen határozni, melyik rekord előzi meg vagy követi az aktuálisat, vagy olyan függvényeket alkalmazhatunk, amelyek eredménye a rekordok sorrendjétől függ. A klasszikus adatbázisok egy teljesen más elven épülnek fel - rekordok gyűjteményét készletként ábrázolják, ahol a rekordok sorrendje elvileg nincs meghatározva.
  • Vektor. A KDB+ kontextusában ez azonos atomi típusú elemek listája, például számok. Más szóval, elemek tömbje. A tömbök a listákkal ellentétben kompaktan tárolhatók és feldolgozhatók vektorprocesszor utasítások segítségével.

 

Történelmi háttér

A KX-et 1993-ban Arthur Whitney alapította, aki korábban a Morgan Stanley Banknál dolgozott az A+ nyelven, amely az APL utódja – egy nagyon eredeti és egy időben népszerű nyelv a pénzügyi világban. Természetesen a KX-ben Arthur ugyanebben a szellemben folytatta, és megalkotta a K vektor-funkcionális nyelvet, a radikális minimalizmus gondolataitól vezérelve. A K programok írásjelek és speciális karakterek zűrzavarának tűnnek, a jelek és a függvények jelentése a kontextustól függ, és minden művelet sokkal több jelentést hordoz, mint a hagyományos programozási nyelvekben. Emiatt egy K-program minimális helyet foglal el – néhány sorral helyettesítheti a szöveg oldalait egy olyan bőbeszédű nyelven, mint a Java –, és az algoritmus szuperkoncentrált megvalósítása.
 
Egy K-beli függvény, amely az LL1 elemző generátor nagy részét egy adott nyelvtan szerint valósítja meg:

1. pp:{q:{(x;p3(),y)};r:$[-11=@x;$x;11=@x;q[`N;$*x];10=abs@@x;q[`N;x]  
2.   ($)~*x;(`P;p3 x 1);(1=#x)&11=@*x;pp[{(1#x;$[2=#x;;,:]1_x)}@*x]  
3.      (?)~*x;(`Q;pp[x 1]);(*)~*x;(`M;pp[x 1]);(+)~*x;(`MP;pp[x 1]);(!)~*x;(`Y;p3 x 1)  
4.      (2=#x)&(@x 1)in 100 101 107 7 -7h;($[(@x 1)in 100 101 107h;`Ff;`Fi];p3 x 1;pp[*x])  
5.      (|)~*x;`S,(pp'1_x);2=#x;`C,{@[@[x;-1+#x;{x,")"}];0;"(",]}({$[".s.C"~4#x;6_-2_x;x]}'pp'x);'`pp];  
6.   $[@r;r;($[1<#r;".s.";""],$*r),$[1<#r;"[",(";"/:1_r),"]";""]]}  

 Arthur a 2003-ban megjelent KDB+-ban testesítette meg az extrém hatékonyság filozófiáját, minimális testmozgással (szerintem most már világos, honnan származik a névben szereplő K betű), és nem más, mint a K negyedik változatának értelmezője. A K K mellé egy felhasználóbarátabb verzió került hozzáadásra Q néven. A Q az SQL egy speciális dialektusának támogatásával - QSQL, valamint az interpreterrel - a táblák támogatása rendszeradattípusként, a táblázatokkal való munkavégzéshez szükséges eszközök memóriában és lemezen stb.
 
A felhasználó szemszögéből tehát a KDB+ egyszerűen egy Q-nyelvi értelmező, amely támogatja a táblákat és a C#-ból származó SQL-szerű LINQ-stílusú kifejezéseket. Ez a legfontosabb különbség a KDB+ és más adatbázisok között, és fő versenyelőnye, amelyet gyakran figyelmen kívül hagynak. Ez nem egy adatbázis + letiltott segédnyelv, hanem egy teljes értékű, erőteljes programozási nyelv + az adatbázis funkciók beépített támogatása. Ez a megkülönböztetés döntő szerepet fog játszani a KDB+ összes előnyének felsorolásában. Például…
 

méret

A modern szabványok szerint a KDB+ egyszerűen mikroszkopikus méretű. Szó szerint egy megabájt alatti végrehajtható fájl és egy kis szövegfájl, néhány rendszerfunkcióval. A valóságban - kevesebb, mint egy megabájt, és ezért a programért a cégek több tízezer dollárt fizetnek évente egy processzorért a szerveren.

  • Ez a méret lehetővé teszi, hogy a KDB+ bármilyen hardveren jól érezze magát – a Pi mikroszámítógéptől a terabájt memóriával rendelkező szerverekig. Ez a funkcionalitást semmilyen módon nem befolyásolja, ráadásul a Q azonnal elindul, így többek között szkriptnyelvként is használható.
  • Ennél a méretnél a Q interpreter teljes egészében belefér a processzor gyorsítótárába, ami felgyorsítja a programvégrehajtást.
  • A végrehajtható fájl ekkora méretével a Q folyamat elhanyagolható helyet foglal el a memóriában, több százat is futtathat. Sőt, ha szükséges, a Q több tíz vagy száz gigabájt memóriával is működhet egyetlen folyamaton belül.

sokoldalúság

A Q számos alkalmazáshoz kiváló. A Q folyamat történelmi adatbázisként működhet, és gyors hozzáférést biztosít terabájtnyi információhoz. Például több tucat előzményadatbázisunk van, amelyek közül néhányban egy tömörítetlen nap több mint 100 gigabájtot foglal el. Azonban ésszerű korlátozások mellett az adatbázis lekérdezése tíz-száz ezredmásodperc alatt fejeződik be. Általában van egy univerzális időtúllépésünk a felhasználói kérésekre - 30 másodperc -, és ez nagyon ritkán működik.
 
A Q ugyanolyan könnyen lehet egy memórián belüli adatbázis. Az új adatok olyan gyorsan kerülnek hozzáadásra a memóriában lévő táblákhoz, hogy a felhasználói kérések korlátozzák. A táblázatokban lévő adatok oszlopokban tárolódnak, ami azt jelenti, hogy az oszlopokon végzett műveletek teljes kapacitással használják a processzor gyorsítótárát. Ezen túlmenően a KX megpróbálta végrehajtani az összes alapvető műveletet, például az aritmetikát a processzor vektoros utasításaival, maximalizálva azok sebességét. A Q olyan feladatokat is végrehajthat, amelyek nem jellemzőek az adatbázisokra - például feldolgozhatja a streaming adatokat, és „valós időben” (a feladattól függően több tíz ezredmásodperctől több másodpercig terjedő késleltetéssel) számolhat különféle aggregációs funkciókat pénzügyi eszközökhöz különböző időre. időközönként, vagy modellt építeni a tökéletes tranzakciók piacra gyakorolt ​​hatásáról, és annak lezárása után szinte azonnal elvégezni a profilalkotást. Az ilyen feladatoknál leggyakrabban nem a Q a fő késleltetés, hanem a különböző forrásokból származó adatok szinkronizálásának szükségessége. A nagy sebesség azáltal érhető el, hogy az adatok és az azokat feldolgozó funkciók egy folyamatban vannak, és a feldolgozás több QSQL-kifejezés és csatlakozás végrehajtására redukálódik, amelyeket nem értelmez, hanem bináris kód hajt végre.
 
Végül a Q-ban bármilyen szolgáltatási folyamatot írhat. Például az átjáró folyamatok, amelyek automatikusan elosztják a felhasználói kéréseket a szükséges adatbázisokhoz és kiszolgálókhoz. A programozónak teljes szabadsága van bármilyen kiegyensúlyozási, prioritási, hibatűrési, hozzáférési jogok, kvóták és lényegében bármi más algoritmus megvalósítására, amire szíve vágyik. A fő probléma itt az, hogy mindezt magának kell megvalósítania.
 
Példaként felsorolom, hogy milyen típusú folyamataink vannak. Mindegyiket aktívan használják és együttműködnek, több tucat különböző adatbázist egyesítenek egybe, több forrásból származó adatokat dolgoznak fel, és több száz felhasználót és alkalmazást szolgálnak ki.

  • Csatlakozók (feedhandler) az adatforrásokhoz. Ezek a folyamatok jellemzően külső könyvtárakat használnak, amelyeket a Q-ba töltenek be. A Q-beli C interfész rendkívül egyszerű, és lehetővé teszi, hogy könnyen létrehozhasson proxyfüggvényeket bármely C/C++ könyvtárhoz. A Q elég gyors ahhoz, hogy kezelje például az összes európai tőzsdéről érkező FIX üzenetek özönét egyidejűleg.
  • Adatforgalmazók (tickerplant), amelyek közbenső kapcsolatként szolgálnak a csatlakozók és a fogyasztók között. Ugyanakkor a bejövő adatokat egy speciális bináris naplóba írják, ami robusztusságot biztosít a fogyasztók számára a kapcsolat elvesztésével vagy újraindításával szemben.
  • In-memory adatbázis (rdb). Ezek az adatbázisok a memóriában tárolva biztosítják a lehető leggyorsabb hozzáférést a nyers, friss adatokhoz. Jellemzően napközben táblázatokban halmozzák fel az adatokat, éjszaka pedig alaphelyzetbe állítják azokat.
  • Persist adatbázis (pdb). Ezek az adatbázisok biztosítják, hogy a mai adatok egy történelmi adatbázisban legyenek tárolva. Az rdb-vel ellentétben általában nem tárolnak adatokat a memóriában, hanem napközben speciális gyorsítótárat használnak a lemezen, és éjfélkor átmásolják az adatokat a történelmi adatbázisba.
  • Történelmi adatbázisok (hdb). Ezek az adatbázisok hozzáférést biztosítanak az előző napok, hónapok és évek adataihoz. Méretüknek (napokban) csak a merevlemezek mérete szab határt. Az adatok bárhol elhelyezhetők, különösen különböző lemezeken a hozzáférés felgyorsítása érdekében. Lehetőség van az adatok tömörítésére több választható algoritmus segítségével. Az adatbázis felépítése jól dokumentált és egyszerű, az adatokat oszloponként, szabályos állományokban tároljuk, így azok akár az operációs rendszer segítségével is feldolgozhatók.
  • Adatbázisok összesített információkkal. Különféle aggregációkat tárolnak, általában a hangszer neve és időintervallum szerint csoportosítva. A memóriában lévő adatbázisok minden bejövő üzenettel frissítik állapotukat, a történeti adatbázisok pedig előre kiszámított adatokat tárolnak, hogy felgyorsítsák az előzményadatokhoz való hozzáférést.
  • Végül, a átjáró folyamatokalkalmazások és felhasználók kiszolgálása. A Q lehetővé teszi a bejövő üzenetek teljesen aszinkron feldolgozását, adatbázisok közötti elosztását, hozzáférési jogok ellenőrzését stb. Vegye figyelembe, hogy az üzenetek nincsenek korlátozva, és legtöbbször nem SQL-kifejezések, ahogy az más adatbázisokban történik. Az SQL kifejezést leggyakrabban egy speciális függvényben rejtik el, és a felhasználó által kért paraméterek alapján állítják össze - az idő konvertálása, szűrése, az adatok normalizálása (például a részvényárfolyam kiegyenlítésre kerül, ha osztalékot fizettek), stb.

Egy adattípus tipikus architektúrája:

KDB+ adatbázis: a pénzügyektől a Forma-1-ig

Sebesség

Bár a Q egy értelmezett nyelv, egyben vektornyelv is. Ez azt jelenti, hogy sok beépített függvény, különösen az aritmetikai, bármilyen formájú argumentumot vesz fel – számokat, vektorokat, mátrixokat, listákat –, és a programozótól elvárható, hogy a programot tömbműveletekként valósítsa meg. Egy ilyen nyelvben, ha két millió elemből álló vektort adunk össze, már nem számít, hogy a nyelv értelmezve van, az összeadást egy szuperoptimalizált bináris függvény hajtja végre. Mivel a Q programokban az idő oroszlánrészét olyan táblákkal végzett műveletekre fordítjuk, amelyek ezeket az alapvető vektorizált függvényeket használják, a kimenet nagyon megfelelő működési sebességet biztosít, ami lehetővé teszi, hogy akár egy folyamatban is hatalmas mennyiségű adatot dolgozzunk fel. Ez hasonló a Python matematikai könyvtáraihoz – bár maga a Python egy nagyon lassú nyelv, számos kiváló könyvtára van, például a numpy, amelyek lehetővé teszik a numerikus adatok feldolgozását egy lefordított nyelv sebességével (mellesleg a numpy ideológiailag közel áll a Q-hoz ).
 
Ezenkívül a KX nagyon körültekintően közelítette meg a táblák tervezését és a velük végzett munka optimalizálását. Először is, többféle index támogatott, amelyeket beépített függvények támogatnak, és nem csak a táblázat oszlopaira, hanem bármilyen vektorra is alkalmazhatók - csoportosítás, rendezés, egyediség attribútum és speciális csoportosítás a történelmi adatbázisokhoz. Az indexet egyszerűen alkalmazza, és automatikusan beállítja, amikor elemeket ad hozzá az oszlophoz/vektorhoz. Az indexek egyformán sikeresen alkalmazhatók a tábla oszlopaira mind a memóriában, mind a lemezen. QSQL lekérdezés végrehajtásakor az indexeket lehetőség szerint automatikusan használja a rendszer. Másodszor, a történeti adatokkal való munka az operációs rendszer fájlok megjelenítési mechanizmusán (memóriatérkép) keresztül történik. A nagy táblák soha nem töltődnek be a memóriába, hanem a szükséges oszlopok közvetlenül a memóriába vannak leképezve, és csak az a rész kerül ténylegesen betöltésre (itt az indexek is segítenek), amelyre szükség van. A programozó számára teljesen mindegy, hogy az adatok a memóriában vannak-e vagy sem; az mmap-pal való munkavégzés mechanizmusa teljesen el van rejtve a Q mélyén.
 
A KDB+ nem relációs adatbázis, a táblák tetszőleges adatokat tartalmazhatnak, míg a sorok sorrendje a táblában nem változik új elemek hozzáadásakor, és használható és kell használni a lekérdezések írásakor. Erre a funkcióra sürgősen szükség van idősorokkal való munkavégzéshez (tőzsdékből származó adatok, telemetria, eseménynaplók), mert ha az adatok idő szerint vannak rendezve, akkor a felhasználónak nem kell semmilyen SQL trükköt használnia az első vagy az utolsó sor vagy az N megtalálásához. sorokat a táblázatban , határozza meg, hogy melyik sor kövesse az N-edik sort stb. A táblázatok összekapcsolása még tovább egyszerűsödik, például 16000 500 VOD.L (Vodafone) tranzakció utolsó árajánlatának megtalálása egy XNUMX millió elemből álló táblázatban körülbelül egy másodpercet vesz igénybe a lemezen, és több tíz ezredmásodpercet a memóriában.
 
Példa időbeli összekapcsolásra - az idézet tábla a memóriába van leképezve, így nem kell megadni a VOD.L-t a hol, a szimmetria oszlop indexe és az adatok idő szerinti rendezése implicit módon kerül felhasználásra. Szinte minden összekapcsolás a Q-ban reguláris függvény, nem egy kiválasztási kifejezés része:

1. aj[`sym`time;select from trade where date=2019.03.26, sym=`VOD.L;select from quote where date=2019.03.26]  

Végül érdemes megjegyezni, hogy a KX mérnökei, kezdve magával Arthur Whitney-vel, valóban megszállottjai a hatékonyságnak, és mindent megtesznek azért, hogy a legtöbbet kihozzák a Q alapfunkcióiból, és optimalizálják a leggyakoribb használati mintákat.
 

Teljes

A KDB+ elsősorban kivételes sokoldalúsága miatt népszerű a vállalkozások körében – egyformán jól használható memória-adatbázisként, terabájtnyi történelmi adatok tárolására szolgáló adatbázisként és adatelemzési platformként. Annak köszönhetően, hogy az adatfeldolgozás közvetlenül az adatbázisban történik, nagy munka- és erőforrás-megtakarítás érhető el. Az adatbázis-funkciókkal integrált teljes értékű programozási nyelv lehetővé teszi a szükséges folyamatok teljes kötegének egy platformon történő megvalósítását - az adatok fogadásától a felhasználói kérések feldolgozásáig.
 

További információ

Korlátozások

A KDB+/Q jelentős hátránya a magas belépési küszöb. A nyelvnek furcsa a szintaxisa, néhány funkció erősen túlterhelt (az értéknek például kb. 11 használati esete van). A legfontosabb, hogy gyökeresen más megközelítést igényel a programok írása. Egy vektoros nyelvben mindig tömbtranszformációkban kell gondolkodni, az összes ciklust a leképezés/kicsinyítés függvények több változatán keresztül kell megvalósítani (amelyeket a Q-ban határozószavaknak neveznek), és soha ne próbáljon pénzt spórolni azzal, hogy a vektorműveleteket atomi műveletekre cseréli. Például egy elem N-edik előfordulásának indexének megkereséséhez egy tömbben a következőket kell írnia:

1. (where element=vector)[N]  

bár ez a C/Java szabványok szerint rettenetesen hatástalannak tűnik (= létrehoz egy logikai vektort, ahol a benne lévő elemek valódi indexeit adja vissza). De ez a jelölés egyértelműbbé teszi a kifejezés jelentését, és a lassú atomi műveletek helyett gyors vektorműveleteket használ. A vektoros nyelvek és a többi nyelv közötti fogalmi különbség összevethető a programozás kötelező és funkcionális megközelítései közötti különbséggel, és erre fel kell készülni.
 
Egyes felhasználók szintén elégedetlenek a QSQL-lel. A lényeg az, hogy csak úgy néz ki, mint az igazi SQL. A valóságban ez csak az SQL-szerű kifejezések értelmezője, amely nem támogatja a lekérdezés optimalizálását. A felhasználónak magának kell optimális lekérdezéseket írnia, és Q-ban, amire sokan nincsenek készen. Másrészt természetesen mindig saját maga is megírhatja az optimális lekérdezést, ahelyett, hogy egy feketedoboz-optimalizálóra hagyatkozna.
 
Plusz, hogy a Q - Q For halandóknak című könyv ingyenesen elérhető a következő címen: cég honlapja, sok más hasznos anyagot is gyűjtöttek ott.
 
Egy másik nagy hátrány a licenc költsége. Ez évente több tízezer dollárt jelent CPU-nként. Ilyen kiadásokat csak a nagyvállalatok engedhetnek meg maguknak. A közelmúltban a KX rugalmasabbá tette engedélyezési politikáját, és lehetőséget biztosít arra, hogy csak a használat idejére fizessen vagy béreljen KDB+-t a Google és az Amazon felhőjében. A KX letöltést is kínál ingyenes verzió nem kereskedelmi célokra (32 bites verzió vagy kérésre 64 bites).
 

versenytársak

Jó néhány speciális, hasonló elvekre épülő adatbázis létezik - oszlopos, memórián belüli, nagyon nagy mennyiségű adatra koncentrálva. A probléma az, hogy ezek speciális adatbázisok. Egy szembetűnő példa a Clickhouse. Ennek az adatbázisnak a KDB+-hoz nagyon hasonló elve van az adatok lemezen való tárolására és az index felépítésére; bizonyos lekérdezéseket gyorsabban hajt végre, mint a KDB+, bár nem jelentős mértékben. De a Clickhouse adatbázisként is specializáltabb, mint a KDB+ - web analytics vs tetszőleges idősorok (ez a különbség nagyon fontos - emiatt pl. a Clickhouse-ban nem lehet használni a rekordok sorrendjét). De ami a legfontosabb, a Clickhouse nem rendelkezik a KDB+ sokoldalúságával, egy olyan nyelvvel, amely lehetővé tenné az adatok közvetlenül az adatbázisban történő feldolgozását, ahelyett, hogy először betöltené őket egy külön alkalmazásba, tetszőleges SQL kifejezéseket építene, tetszőleges függvényeket alkalmazna egy lekérdezésben, folyamatokat hozna létre. nem kapcsolódik a történeti adatbázis-funkciók végrehajtásához. Emiatt nehéz összehasonlítani a KDB+-t más adatbázisokkal, lehet, hogy bizonyos felhasználási esetekben jobbak, vagy egyszerűen jobbak a klasszikus adatbázis-feladatoknál, de nem ismerek másik, hasonlóan hatékony és sokoldalú eszközt az ideiglenes adatok feldolgozására.
 

Python integráció

Annak érdekében, hogy a KDB+ könnyebben használható legyen a technológiát nem ismerők számára, a KX olyan könyvtárakat hozott létre, amelyek egyetlen folyamaton belül szorosan integrálódnak a Pythonba. Bármely Python-függvényt meghívhat a Q-ból, vagy fordítva - hívhat meg bármely Q-függvényt a Pythonból (különösen a QSQL-kifejezéseket). A könyvtárak szükség esetén (nem mindig a hatékonyság érdekében) konvertálják az adatokat egyik nyelv formátumából egy másik nyelv formátumába. Ennek eredményeként a Q és a Python olyan szoros szimbiózisban élnek, hogy a határok közöttük elmosódnak. Ennek eredményeként a programozó egyrészt teljes hozzáféréssel rendelkezik számos hasznos Python könyvtárhoz, másrészt gyors alapot kap a Pythonba integrált nagy adatokkal való munkavégzéshez, ami különösen hasznos a gépi tanulással foglalkozók számára. vagy modellezés.
 
A Q használata Pythonban:

1. >>> q()  
2.q)trade:([]date:();sym:();qty:())  
3. q)  
4. >>> q.insert('trade', (date(2006,10,6), 'IBM', 200))  
5. k(',0')  
6. >>> q.insert('trade', (date(2006,10,6), 'MSFT', 100))  
7. k(',1')  

referenciák

A cég oldala - https://kx.com/
Weboldal fejlesztőknek - https://code.kx.com/v2/
Q könyv halandóknak (angol nyelven) - https://code.kx.com/q4m3/
Cikkek a KDB+/Q alkalmazásairól a kx alkalmazottaitól - https://code.kx.com/v2/wp/

Forrás: will.com

Hozzászólás