Base de dades KDB+: de les finances a la Fórmula 1

KDB+, producte de l'empresa KX és una base de dades de columna molt coneguda en cercles estrets, extremadament ràpida i dissenyada per emmagatzemar sèries temporals i càlculs analítics basats en elles. Inicialment, era (i és) molt popular a la indústria financera: l'utilitzen tots els 10 principals bancs d'inversió i molts fons de cobertura, intercanvis i altres organitzacions coneguts. Recentment, KX ha decidit ampliar la seva base de clients i ara oferir solucions en altres àmbits on hi ha una gran quantitat de dades, organitzades per temps o no: telecomunicacions, bioinformàtica, fabricació, etc. També es van convertir en socis de l'equip Aston Martin Red Bull Racing a la Fórmula 1, on ajuden a recollir i processar dades dels sensors dels cotxes i analitzar les proves del túnel de vent. En aquest article, vull dir-vos quines característiques de KDB+ fan que sigui de gran rendiment, per què les empreses estan disposades a gastar-hi molts diners i, finalment, per què no és realment una base de dades.
 
Base de dades KDB+: de les finances a la Fórmula 1
 
En aquest article intentaré explicar-vos en general què és KDB+, quines capacitats i limitacions té i quins són els seus beneficis per a les empreses que volen processar grans quantitats de dades. No entraré en els detalls de la implementació de KDB+ ni els detalls del seu llenguatge de programació Q. Tots dos temes són molt amplis i mereixen articles separats. Es pot trobar molta informació sobre aquests temes a code.kx.com, inclòs un llibre sobre Q - Q For Mortals (vegeu l'enllaç següent).

Alguns termes

  • Base de dades en memòria. Una base de dades que emmagatzema dades a la memòria RAM per a un accés més ràpid. Els avantatges d'aquesta base de dades són clars, però els desavantatges són la possibilitat de pèrdua de dades i la necessitat de tenir molta memòria al servidor.
  • Base de dades columnar. Una base de dades on les dades s'emmagatzemen columna per columna en lloc de registre per registre. El principal avantatge d'aquesta base de dades és que les dades d'una columna s'emmagatzemen al disc i a la memòria, la qual cosa accelera significativament l'accés a ella. No cal carregar columnes que no s'utilitzen a la consulta. El principal desavantatge és que és difícil modificar i eliminar registres.
  • Sèries temporals. Dades amb una columna de data o hora. Normalment, l'ordre temporal és important per a aquestes dades, de manera que podeu determinar fàcilment quin registre precedeix o segueix l'actual, o bé per aplicar funcions els resultats de les quals depenen de l'ordre dels registres. Les bases de dades clàssiques es construeixen sobre un principi completament diferent: representar una col·lecció de registres com un conjunt, on l'ordre dels registres, en principi, no està definit.
  • Vector. En el context de KDB+, aquesta és una llista d'elements del mateix tipus atòmic, per exemple, nombres. En altres paraules, un conjunt d'elements. Les matrius, a diferència de les llistes, es poden emmagatzemar de manera compacta i processar-se mitjançant instruccions del processador vectorial.

 

La informació històrica

KX va ser fundada l'any 1993 per Arthur Whitney, que anteriorment va treballar al Morgan Stanley Bank en l'idioma A+, el successor de l'APL, un llenguatge molt original i alhora popular al món financer. Per descomptat, a KX, Arthur va continuar amb el mateix esperit i va crear el llenguatge vectorial-funcional K, guiat per les idees del minimalisme radical. Els programes K semblen una barreja de signes de puntuació i caràcters especials, el significat dels signes i les funcions depèn del context i cada operació té molt més significat que en els llenguatges de programació convencionals. A causa d'això, un programa K ocupa un espai mínim (unes poques línies poden substituir pàgines de text en un llenguatge prolix com Java) i és una implementació súper concentrada de l'algorisme.
 
Una funció en K que implementa la major part del generador d'analitzadors LL1 segons una gramàtica determinada:

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 va plasmar aquesta filosofia d'eficàcia extrema amb un mínim de moviments corporals a KDB+, que va aparèixer l'any 2003 (crec que ara està clar d'on ve la lletra K del nom) i no és més que un intèrpret de la quarta versió de la K. S'ha afegit una versió més fàcil d'utilitzar a sobre de K K anomenada Q. Q també ha afegit suport per a un dialecte específic de SQL - QSQL, i l'intèrpret - suport per a taules com a tipus de dades del sistema, eines per treballar amb taules. a la memòria i al disc, etc.
 
Per tant, des de la perspectiva d'un usuari, KDB+ és simplement un intèrpret de llenguatge Q amb suport per a taules i expressions d'estil LINQ semblants a SQL de C#. Aquesta és la diferència més important entre KDB+ i altres bases de dades i el seu principal avantatge competitiu, que sovint es passa per alt. No és una base de dades + llenguatge auxiliar desactivat, sinó un llenguatge de programació potent i complet + suport integrat per a les funcions de la base de dades. Aquesta distinció jugarà un paper decisiu a l'hora d'enumerar tots els avantatges de KDB+. Per exemple…
 

mida

Segons els estàndards moderns, KDB+ és simplement de mida microscòpica. És literalment un fitxer executable de sub-megabyte i un petit fitxer de text amb algunes funcions del sistema. En realitat, menys d'un megabyte, i per a aquest programa les empreses paguen desenes de milers de dòlars l'any per un processador al servidor.

  • Aquesta mida permet que KDB+ se senti bé en qualsevol maquinari, des d'un microordinador Pi fins a servidors amb terabytes de memòria. Això no afecta de cap manera la funcionalitat; a més, Q s'inicia a l'instant, la qual cosa permet utilitzar-lo, entre altres coses, com a llenguatge de script.
  • Amb aquesta mida, l'intèrpret Q encaixa completament a la memòria cau del processador, la qual cosa accelera l'execució del programa.
  • Amb aquesta mida del fitxer executable, el procés Q ocupa un espai insignificant a la memòria; podeu executar-ne centenars. A més, si cal, Q pot funcionar amb desenes o centenars de gigabytes de memòria dins d'un sol procés.

versatilitat

Q és ideal per a una àmplia gamma d'aplicacions. El procés Q pot actuar com una base de dades històrica i proporcionar un accés ràpid a terabytes d'informació. Per exemple, tenim desenes de bases de dades històriques, en algunes de les quals un dia de dades sense comprimir ocupa més de 100 gigabytes. Tanmateix, sota restriccions raonables, una consulta a la base de dades es completarà en desenes o centenars de mil·lisegons. En general, tenim un temps d'espera universal per a les sol·licituds dels usuaris -30 segons- i funciona molt poques vegades.
 
Q podria ser amb la mateixa facilitat una base de dades a la memòria. Les noves dades s'afegeixen a les taules en memòria tan ràpidament que les sol·licituds dels usuaris són el factor limitant. Les dades de les taules s'emmagatzemen en columnes, el que significa que qualsevol operació en una columna utilitzarà la memòria cau del processador a plena capacitat. A més d'això, KX va intentar implementar totes les operacions bàsiques com l'aritmètica mitjançant instruccions vectorials del processador, maximitzant la seva velocitat. Q també pot realitzar tasques que no són típiques de les bases de dades, per exemple, processar dades de transmissió en temps real i calcular en "temps real" (amb un retard de desenes de mil·lisegons a diversos segons depenent de la tasca) diverses funcions d'agregació per a instruments financers durant diferents temps. intervals o construir un model de la influència de les transaccions perfectes al mercat i realitzar el seu perfil gairebé immediatament després de la seva finalització. En aquestes tasques, sovint el retard principal no és Q, sinó la necessitat de sincronitzar dades de diferents fonts. S'aconsegueix una alta velocitat pel fet que les dades i les funcions que les processen es troben en un sol procés, i el processament es redueix a executar diverses expressions i unions QSQL, que no s'interpreten, sinó que s'executen mitjançant codi binari.
 
Finalment, podeu escriure qualsevol procés de servei a Q. Per exemple, els processos de passarel·la que distribueixen automàticament les sol·licituds dels usuaris a les bases de dades i servidors necessaris. El programador té total llibertat per implementar qualsevol algorisme per a l'equilibri, la priorització, la tolerància a errors, els drets d'accés, les quotes i, bàsicament, qualsevol altra cosa que el seu cor desitgi. El principal problema aquí és que tot això ho haureu d'implementar vosaltres mateixos.
 
Com a exemple, enumeraré quins tipus de processos tenim. Tots ells s'utilitzen activament i treballen junts, combinant desenes de bases de dades diferents en una, processant dades de diverses fonts i donant servei a centenars d'usuaris i aplicacions.

  • Connectors (feedhandler) a fonts de dades. Aquests processos solen utilitzar biblioteques externes que es carreguen a Q. La interfície C a Q és extremadament senzilla i us permet crear fàcilment funcions proxy per a qualsevol biblioteca C/C++. Q és prou ràpid per gestionar, per exemple, el processament simultània d'una gran quantitat de missatges FIX de totes les borses europees.
  • Distribuïdors de dades (tickerplant), que serveixen d'enllaç intermedi entre connectors i consumidors. Al mateix temps, escriuen les dades entrants en un registre binari especial, proporcionant robustesa als consumidors davant pèrdues de connexió o reinicis.
  • Base de dades en memòria (rdb). Aquestes bases de dades proporcionen l'accés més ràpid possible a dades fresques i en brut emmagatzemant-les a la memòria. Normalment, acumulen dades en taules durant el dia i les restableixen a la nit.
  • Base de dades Persist (pdb). Aquestes bases de dades garanteixen que les dades d'avui s'emmagatzemen en una base de dades històrica. Per regla general, a diferència de rdb, no emmagatzemen dades a la memòria, sinó que utilitzen una memòria cau especial al disc durant el dia i copien les dades a la mitjanit a la base de dades històrica.
  • Bases de dades històriques (hdb). Aquestes bases de dades proporcionen accés a les dades dels dies, mesos i anys anteriors. La seva mida (en dies) només està limitada per la mida dels discs durs. Les dades es poden localitzar a qualsevol lloc, en particular en diferents discs per accelerar l'accés. És possible comprimir dades utilitzant diversos algorismes per triar. L'estructura de la base de dades està ben documentada i senzilla, les dades s'emmagatzemen columna per columna en fitxers habituals, de manera que es puguin processar, fins i tot mitjançant el sistema operatiu.
  • Bases de dades amb informació agregada. Emmagatzemen diverses agregacions, generalment amb, agrupades per nom de l'instrument i interval de temps. Les bases de dades en memòria actualitzen el seu estat amb cada missatge entrant i les bases de dades històriques emmagatzemen dades precalculades per accelerar l'accés a les dades històriques.
  • Finalment processos de passarel·laservei d'aplicacions i usuaris. Q us permet implementar un processament completament asíncron dels missatges entrants, distribuir-los entre bases de dades, comprovar els drets d'accés, etc. Tingueu en compte que els missatges no estan limitats i que la majoria de vegades no són expressions SQL, com és el cas d'altres bases de dades. Molt sovint, l'expressió SQL s'amaga en una funció especial i es construeix a partir dels paràmetres sol·licitats per l'usuari: el temps es converteix, es filtra, les dades es normalitzen (per exemple, el preu de les accions s'iguala si es pagaven dividends), etc.

Arquitectura típica per a un tipus de dades:

Base de dades KDB+: de les finances a la Fórmula 1

Accelerar

Encara que Q és un llenguatge interpretat, també és un llenguatge vectorial. Això vol dir que moltes funcions integrades, especialment les aritmètiques, prenen arguments de qualsevol forma (números, vectors, matrius, llistes) i s'espera que el programador implementi el programa com a operacions de matriu. En aquest llenguatge, si afegiu dos vectors d'un milió d'elements, ja no importa que el llenguatge s'interpreti; l'addició es farà mitjançant una funció binària superoptimitzada. Com que la major part del temps als programes Q es dedica a operacions amb taules que utilitzen aquestes funcions bàsiques vectoritzades, la sortida és una velocitat operativa molt decent, que ens permet processar una gran quantitat de dades fins i tot en un sol procés. Això és similar a les biblioteques matemàtiques de Python; encara que Python en si és un llenguatge molt lent, té moltes biblioteques excel·lents com numpy que us permeten processar dades numèriques a la velocitat d'un llenguatge compilat (per cert, numpy és ideològicament proper a Q. ).
 
A més, KX va adoptar un enfocament molt acurat per dissenyar taules i optimitzar el treball amb elles. En primer lloc, s'admeten diversos tipus d'índexs, que són compatibles amb funcions integrades i que es poden aplicar no només a les columnes de la taula, sinó també a qualsevol vector: agrupació, ordenació, atribut d'unicitat i agrupació especial per a bases de dades històriques. L'índex s'aplica de manera senzilla i s'ajusta automàticament quan s'afegeixen elements a la columna/vector. Els índexs es poden aplicar igualment correctament a les columnes de la taula tant a la memòria com al disc. Quan s'executa una consulta QSQL, els índexs s'utilitzen automàticament si és possible. En segon lloc, el treball amb dades històriques es fa mitjançant el mecanisme de visualització de fitxers del sistema operatiu (mapa de memòria). Les taules grans mai es carreguen a la memòria; en canvi, les columnes necessàries es mapegen directament a la memòria i només es carrega realment aquella part d'elles (els índexs també ajuden aquí) que són necessàries. El programador no té cap diferència si les dades estan a la memòria o no; el mecanisme per treballar amb mmap està completament ocult a les profunditats de Q.
 
KDB+ no és una base de dades relacional; les taules poden contenir dades arbitràries, mentre que l'ordre de les files de la taula no canvia quan s'afegeixen nous elements i es pot i s'ha d'utilitzar quan escriuen consultes. Aquesta característica és necessària amb urgència per treballar amb sèries temporals (dades d'intercanvis, telemetria, registres d'esdeveniments), perquè si les dades s'ordenen per temps, l'usuari no necessita utilitzar cap truc SQL per trobar la primera o l'última fila o N. files de la taula , determineu quina línia segueix la línia N, etc. Les unions de taules es simplifiquen encara més, per exemple, trobar l'última cotització per a 16000 transaccions VOD.L (Vodafone) en una taula de 500 milions d'elements triga aproximadament un segon al disc i desenes de mil·lisegons a la memòria.
 
Un exemple d'unió de temps: la taula de cotitzacions s'assigna a la memòria, de manera que no cal especificar VOD.L on s'utilitzen implícitament l'índex de la columna sym i el fet que les dades estan ordenades per temps. Gairebé totes les unions a Q són funcions regulars, no formen part d'una expressió seleccionada:

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

Finalment, val la pena assenyalar que els enginyers de KX, començant pel mateix Arthur Whitney, estan realment obsessionats amb l'eficiència i fan tot el possible per treure el màxim profit de les funcions estàndard de la Q i optimitzar els patrons d'ús més habituals.
 

Total

KDB+ és popular entre les empreses principalment per la seva versatilitat excepcional: serveix igualment com a base de dades en memòria, com a base de dades per emmagatzemar terabytes de dades històriques i com a plataforma per a l'anàlisi de dades. A causa del fet que el processament de dades es produeix directament a la base de dades, s'aconsegueix una gran velocitat de treball i estalvi de recursos. Un llenguatge de programació complet integrat amb les funcions de la base de dades us permet implementar tota la pila de processos necessaris en una plataforma, des de rebre dades fins a processar les sol·licituds dels usuaris.
 

Per obtenir més informació,

Limitacions

Un desavantatge important de KDB+/Q és el llindar d'entrada alt. El llenguatge té una sintaxi estranya, algunes funcions estan molt sobrecarregades (el valor, per exemple, té uns 11 casos d'ús). El més important és que requereix un enfocament radicalment diferent per escriure programes. En un llenguatge vectorial, sempre s'ha de pensar en termes de transformacions de matriu, implementar tots els bucles a través de diverses variants de les funcions map/reduce (que s'anomenen adverbis a Q) i mai intentar estalviar diners substituint les operacions vectorials per atòmiques. Per exemple, per trobar l'índex de l'enèsima ocurrència d'un element en una matriu, hauríeu d'escriure:

1. (where element=vector)[N]  

tot i que això sembla terriblement ineficient per als estàndards C/Java (= crea un vector booleà, on retorna els índexs reals dels elements que hi ha). Però aquesta notació fa que el significat de l'expressió sigui més clar i utilitzeu operacions vectorials ràpides en lloc de les atòmiques lentes. La diferència conceptual entre un llenguatge vectorial i altres és comparable a la diferència entre els enfocaments imperatius i funcionals de la programació, i cal que estigueu preparats per a això.
 
Alguns usuaris també no estan satisfets amb QSQL. La qüestió és que només sembla un SQL real. En realitat, només és un intèrpret d'expressions semblants a SQL que no admet l'optimització de consultes. L'usuari ha d'escriure les consultes òptimes ell mateix, i en Q, per a les quals moltes no estan preparats. D'altra banda, per descomptat, sempre podeu escriure la consulta òptima vosaltres mateixos, en lloc de confiar en un optimitzador de caixa negra.
 
Com a avantatge, un llibre sobre Q - Q For Mortals està disponible gratuïtament a lloc web de l'empresa, també s'hi recullen molts altres materials útils.
 
Un altre gran desavantatge és el cost de la llicència. Això són desenes de milers de dòlars anuals per CPU. Només les grans empreses es poden permetre aquestes despeses. Recentment, KX ha flexibilitzat la seva política de llicències i ofereix l'oportunitat de pagar només pel temps d'ús o llogar KDB+ als núvols de Google i Amazon. KX també ofereix per descarregar versió gratuïta per a finalitats no comercials (versió de 32 bits o 64 bits a petició).
 

Competidors

Hi ha força bases de dades especialitzades construïdes amb principis similars: columnars, en memòria, centrades en quantitats molt grans de dades. El problema és que es tracta de bases de dades especialitzades. Un exemple sorprenent és Clickhouse. Aquesta base de dades té un principi molt similar al KDB+ per emmagatzemar dades al disc i construir un índex; realitza algunes consultes més ràpidament que KDB+, encara que no de manera significativa. Però fins i tot com a base de dades, Clickhouse està més especialitzat que KDB+: anàlisi web vs sèries temporals arbitràries (aquesta diferència és molt important; per això, per exemple, a Clickhouse no és possible utilitzar l'ordenació de registres). Però, el més important, Clickhouse no té la versatilitat de KDB+, un llenguatge que permetria processar dades directament a la base de dades, en lloc de carregar-les primer en una aplicació separada, construir expressions SQL arbitràries, aplicar funcions arbitràries en una consulta, crear processos. no relacionat amb l'execució de funcions de bases de dades històriques. Per tant, és difícil comparar KDB+ amb altres bases de dades; poden ser millors en determinats casos d'ús o simplement millor quan es tracta de tasques de bases de dades clàssiques, però no conec una altra eina igual d'eficaç i versàtil per processar dades temporals.
 

Integració de Python

Per fer que KDB+ sigui més fàcil d'utilitzar per a persones que no estan familiaritzades amb la tecnologia, KX va crear biblioteques per integrar-se estretament amb Python dins d'un sol procés. Podeu cridar a qualsevol funció de Python des de Q, o viceversa: cridar a qualsevol funció Q des de Python (en particular, expressions QSQL). Les biblioteques converteixen, si cal (no sempre per motius d'eficiència), dades del format d'un idioma al format d'un altre. Com a resultat, Q i Python viuen en una simbiosi tan estreta que els límits entre ells es desdibuixen. Com a resultat, el programador, d'una banda, té accés complet a nombroses biblioteques útils de Python, d'altra banda, rep una base ràpida per treballar amb grans dades integrades a Python, que és especialment útil per a aquells que participen en l'aprenentatge automàtic. o modelatge.
 
Treballant amb Q a Python:

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')  

Referències

El lloc de l'empresa - https://kx.com/
Lloc web per a desenvolupadors - https://code.kx.com/v2/
Llibre Q For Mortals (en anglès) - https://code.kx.com/q4m3/
Articles sobre aplicacions KDB+/Q dels empleats de kx - https://code.kx.com/v2/wp/

Font: www.habr.com

Afegeix comentari