Base de datos KDB+: de las finanzas a la Fórmula 1

KDB+, producto de empresa KX es una base de datos en columnas, extremadamente rápida y ampliamente conocida en círculos reducidos, diseñada para almacenar series temporales y cálculos analíticos basados ​​en ellas. Inicialmente, era (y es) muy popular en la industria financiera: lo utilizan los 10 principales bancos de inversión y muchos fondos de cobertura, bolsas y otras organizaciones conocidas. Recientemente, KX decidió ampliar su base de clientes y ahora ofrece soluciones en otras áreas donde hay una gran cantidad de datos, organizados por tiempo o de otro modo: telecomunicaciones, bioinformática, fabricación, etc. También se convirtieron en socios del equipo Aston Martin Red Bull Racing en la Fórmula 1, donde ayudan a recopilar y procesar datos de los sensores de los automóviles y analizar las pruebas del túnel de viento. En este artículo, quiero contarles qué características de KDB+ lo hacen de gran rendimiento, por qué las empresas están dispuestas a gastar mucho dinero en él y, finalmente, por qué no es realmente una base de datos.
 
Base de datos KDB+: de las finanzas a la Fórmula 1
 
En este artículo intentaré contarte de forma general qué es KDB+, qué capacidades y limitaciones tiene y cuáles son sus beneficios para las empresas que quieren procesar grandes cantidades de datos. No entraré en detalles sobre la implementación de KDB+ ni sobre su lenguaje de programación Q. Ambos temas son muy amplios y merecen artículos separados. Se puede encontrar mucha información sobre estos temas en code.kx.com, incluido un libro sobre Q - Q For Mortals (ver enlace a continuación).

Algunos términos

  • Base de datos en memoria. Una base de datos que almacena datos en RAM para un acceso más rápido. Las ventajas de una base de datos de este tipo son claras, pero las desventajas son la posibilidad de pérdida de datos y la necesidad de tener mucha memoria en el servidor.
  • Base de datos en columnas. Una base de datos donde los datos se almacenan columna por columna en lugar de registro por registro. La principal ventaja de una base de datos de este tipo es que los datos de una columna se almacenan juntos en el disco y en la memoria, lo que acelera significativamente el acceso a ella. No es necesario cargar columnas que no se utilizan en la consulta. La principal desventaja es que es difícil modificar y eliminar registros.
  • Series de tiempo. Datos con una columna de fecha u hora. Normalmente, el orden temporal es importante para dichos datos, de modo que pueda determinar fácilmente qué registro precede o sigue al actual, o para aplicar funciones cuyos resultados dependen del orden de los registros. Las bases de datos clásicas se basan en un principio completamente diferente: representar una colección de registros como un conjunto, donde el orden de los registros, en principio, no está definido.
  • Vector. En el contexto de KDB+, esta es una lista de elementos del mismo tipo atómico, por ejemplo, números. En otras palabras, una serie de elementos. Las matrices, a diferencia de las listas, se pueden almacenar de forma compacta y procesar mediante instrucciones del procesador vectorial.

 

La información histórica

KX fue fundada en 1993 por Arthur Whitney, quien anteriormente trabajó en Morgan Stanley Bank en el lenguaje A+, el sucesor de APL, un lenguaje muy original y en algún momento popular en el mundo financiero. Por supuesto, en KX, Arthur continuó con el mismo espíritu y creó el lenguaje vectorial funcional K, guiado por las ideas del minimalismo radical. Los programas K parecen una mezcla de puntuación y caracteres especiales, el significado de los signos y funciones depende del contexto y cada operación tiene mucho más significado que en los lenguajes de programación convencionales. Debido a esto, un programa K ocupa un espacio mínimo (unas pocas líneas pueden reemplazar páginas de texto en un lenguaje detallado como Java) y es una implementación súper concentrada del algoritmo.
 
Una función en K que implementa la mayor parte del generador de analizadores LL1 de acuerdo con 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 encarnó esta filosofía de extrema eficiencia con un mínimo de movimientos corporales en KDB+, que apareció en 2003 (creo que ahora está claro de dónde viene la letra K del nombre) y no es más que un intérprete de la cuarta versión de la K. lenguaje Se ha agregado una versión más fácil de usar encima de K K llamada Q. Q también agregó soporte para un dialecto específico de SQL - QSQL, y el intérprete - soporte para tablas como tipo de datos del sistema, herramientas para trabajar con tablas en memoria y en disco, etc.
 
Entonces, desde la perspectiva del usuario, KDB+ es simplemente un intérprete de lenguaje Q con soporte para tablas y expresiones de estilo LINQ similares a SQL de C#. Ésta es la diferencia más importante entre KDB+ y otras bases de datos y su principal ventaja competitiva, que a menudo se pasa por alto. Esta no es una base de datos + un lenguaje auxiliar deshabilitado, sino un potente lenguaje de programación completo + soporte integrado para funciones de base de datos. Esta distinción jugará un papel decisivo a la hora de enumerar todos los beneficios de KDB+. Por ejemplo…
 

tamaño

Según los estándares modernos, KDB+ tiene un tamaño simplemente microscópico. Es literalmente un archivo ejecutable de menos de un megabyte y un pequeño archivo de texto con algunas funciones del sistema. En realidad, menos de un megabyte, y por este programa las empresas pagan decenas de miles de dólares al año por un procesador en el servidor.

  • Este tamaño permite que KDB+ funcione perfectamente en cualquier hardware, desde una microcomputadora Pi hasta servidores con terabytes de memoria. Esto no afecta en modo alguno a la funcionalidad; además, Q se inicia instantáneamente, lo que permite utilizarlo, entre otras cosas, como lenguaje de scripting.
  • Con este tamaño, el intérprete Q cabe completamente en la memoria caché del procesador, lo que acelera la ejecución del programa.
  • Con este tamaño de archivo ejecutable, el proceso Q ocupa un espacio insignificante en la memoria; puedes ejecutar cientos de ellos. Además, si es necesario, Q puede operar con decenas o cientos de gigabytes de memoria dentro de un solo proceso.

Universalismo

Q es ideal para una amplia gama de aplicaciones. Process Q puede actuar como una base de datos histórica y proporcionar acceso rápido a terabytes de información. Por ejemplo, tenemos decenas de bases de datos históricas, en algunas de las cuales un día de datos sin comprimir ocupa más de 100 gigabytes. Sin embargo, bajo restricciones razonables, una consulta a la base de datos se completará en decenas o cientos de milisegundos. En general, tenemos un tiempo de espera universal para las solicitudes de los usuarios (30 segundos) y funciona muy raramente.
 
Q podría ser fácilmente una base de datos en memoria. Se agregan nuevos datos a las tablas en memoria con tanta rapidez que las solicitudes de los usuarios son el factor limitante. Los datos de las tablas se almacenan en columnas, lo que significa que cualquier operación en una columna utilizará la memoria caché del procesador a plena capacidad. Además de esto, KX intentó implementar todas las operaciones básicas como la aritmética a través de instrucciones vectoriales del procesador, maximizando su velocidad. Q también puede realizar tareas que no son típicas de las bases de datos, por ejemplo, procesar datos en tiempo real y calcular en "tiempo real" (con un retraso de decenas de milisegundos a varios segundos, según la tarea) varias funciones de agregación de instrumentos financieros en diferentes momentos. intervalos o construir un modelo de la influencia de las transacciones perfectas en el mercado y realizar su perfil casi inmediatamente después de su finalización. En tales tareas, la mayoría de las veces el retraso de tiempo principal no es Q, sino la necesidad de sincronizar datos de diferentes fuentes. La alta velocidad se logra debido a que los datos y las funciones que los procesan están en un solo proceso, y el procesamiento se reduce a ejecutar varias expresiones QSQL y uniones, que no se interpretan, sino que se ejecutan mediante código binario.
 
Finalmente, puede escribir cualquier proceso de servicio en Q. Por ejemplo, procesos de Gateway que distribuyen automáticamente las solicitudes de los usuarios a las bases de datos y servidores necesarios. El programador tiene total libertad para implementar cualquier algoritmo de equilibrio, priorización, tolerancia a fallas, derechos de acceso, cuotas y básicamente cualquier otra cosa que desee. El principal problema aquí es que tendrás que implementar todo esto tú mismo.
 
Como ejemplo, enumeraré qué tipos de procesos tenemos. Todos ellos se utilizan activamente y trabajan juntos, combinando docenas de bases de datos diferentes en una, procesando datos de múltiples fuentes y sirviendo a cientos de usuarios y aplicaciones.

  • Conectores (feedhandler) a fuentes de datos. Estos procesos normalmente utilizan bibliotecas externas que se cargan en Q. La interfaz C en Q es extremadamente simple y le permite crear fácilmente funciones proxy para cualquier biblioteca C/C++. Q es lo suficientemente rápido como para manejar, por ejemplo, procesar una avalancha de mensajes FIX de todas las bolsas de valores europeas simultáneamente.
  • Distribuidores de datos (tickerplant), que sirven como vínculo intermedio entre los conectores y los consumidores. Al mismo tiempo, escriben los datos entrantes en un registro binario especial, lo que brinda solidez a los consumidores contra pérdidas o reinicios de conexión.
  • Base de datos en memoria (rdb). Estas bases de datos proporcionan el acceso más rápido posible a datos nuevos y sin procesar almacenándolos en la memoria. Normalmente, acumulan datos en tablas durante el día y los restablecen por la noche.
  • Base de datos persistente (pdb). Estas bases de datos garantizan que los datos de hoy se almacenen en una base de datos histórica. Como regla general, a diferencia de rdb, no almacenan datos en la memoria, sino que usan un caché especial en el disco durante el día y copian los datos a medianoche a la base de datos histórica.
  • Bases de datos históricas (hdb). Estas bases de datos brindan acceso a datos de días, meses y años anteriores. Su tamaño (en días) está limitado únicamente por el tamaño de los discos duros. Los datos se pueden ubicar en cualquier lugar, en particular en diferentes discos para acelerar el acceso. Es posible comprimir datos utilizando varios algoritmos para elegir. La estructura de la base de datos está bien documentada y es sencilla, los datos se almacenan columna por columna en archivos normales, para que puedan procesarse, incluso mediante el sistema operativo.
  • Bases de datos con información agregada. Almacenan varias agregaciones, generalmente agrupadas por nombre de instrumento e intervalo de tiempo. Las bases de datos en memoria actualizan su estado con cada mensaje entrante y las bases de datos históricas almacenan datos precalculados para acelerar el acceso a los datos históricos.
  • Por último, la procesos de puerta de enlaceservicio de aplicaciones y usuarios. Q le permite implementar un procesamiento completamente asincrónico de los mensajes entrantes, distribuyéndolos entre bases de datos, verificando los derechos de acceso, etc. Tenga en cuenta que los mensajes no están limitados y, en la mayoría de los casos, no son expresiones SQL, como ocurre en otras bases de datos. La mayoría de las veces, la expresión SQL está oculta en una función especial y se construye en función de los parámetros solicitados por el usuario: el tiempo se convierte, se filtra, los datos se normalizan (por ejemplo, el precio de las acciones se iguala si se pagaron dividendos), etc.

Arquitectura típica para un tipo de datos:

Base de datos KDB+: de las finanzas a la Fórmula 1

velocidad

Aunque Q es un lenguaje interpretado, también es un lenguaje vectorial. Esto significa que muchas funciones integradas, particularmente las aritméticas, toman argumentos de cualquier forma (números, vectores, matrices, listas) y se espera que el programador implemente el programa como operaciones de matriz. En un lenguaje así, si sumas dos vectores de un millón de elementos, ya no importa que se interprete el lenguaje; la suma se realizará mediante una función binaria superoptimizada. Dado que la mayor parte del tiempo en los programas Q se dedica a operaciones con tablas que utilizan estas funciones vectorizadas básicas, el resultado es una velocidad operativa muy decente, lo que nos permite procesar una gran cantidad de datos incluso en un solo proceso. Esto es similar a las bibliotecas matemáticas en Python: aunque Python en sí es un lenguaje muy lento, tiene muchas bibliotecas excelentes como numpy que le permiten procesar datos numéricos a la velocidad de un lenguaje compilado (por cierto, numpy es ideológicamente cercano a Q ).
 
Además, KX abordó con mucho cuidado el diseño de las mesas y la optimización del trabajo con ellas. En primer lugar, se admiten varios tipos de índices, que son compatibles con funciones integradas y se pueden aplicar no solo a las columnas de la tabla, sino también a cualquier vector: agrupación, clasificación, atributo de unicidad y agrupación especial para bases de datos históricas. El índice se aplica de forma sencilla y se ajusta automáticamente al agregar elementos a la columna/vector. Los índices se pueden aplicar con igual éxito a las columnas de la tabla tanto en la memoria como en el disco. Al ejecutar una consulta QSQL, los índices se utilizan automáticamente si es posible. En segundo lugar, el trabajo con datos históricos se realiza a través del mecanismo de visualización de archivos del sistema operativo (mapa de memoria). Las tablas grandes nunca se cargan en la memoria; en cambio, las columnas necesarias se asignan directamente a la memoria y solo se carga la parte de ellas (los índices también ayudan aquí) que son necesarias. Al programador le da igual si los datos están en la memoria o no; el mecanismo para trabajar con mmap está completamente oculto en las profundidades de Q.
 
KDB+ no es una base de datos relacional; las tablas pueden contener datos arbitrarios, mientras que el orden de las filas en la tabla no cambia cuando se agregan nuevos elementos y puede y debe usarse al escribir consultas. Esta característica se necesita con urgencia para trabajar con series de tiempo (datos de intercambios, telemetría, registros de eventos), porque si los datos se ordenan por tiempo, entonces el usuario no necesita usar ningún truco de SQL para encontrar la primera o la última fila o N filas de la tabla, determine qué línea sigue a la enésima línea, etc. Las uniones de tablas se simplifican aún más; por ejemplo, encontrar la última cotización de 16000 transacciones VOD.L (Vodafone) en una tabla de 500 millones de elementos lleva aproximadamente un segundo en el disco y decenas de milisegundos en la memoria.
 
Un ejemplo de combinación de tiempo: la tabla de cotizaciones se asigna a la memoria, por lo que no es necesario especificar VOD.L en dónde, se utilizan implícitamente el índice de la columna sym y el hecho de que los datos están ordenados por tiempo. Casi todas las combinaciones en Q son funciones regulares, no forman parte de una expresión de selección:

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

Finalmente, vale la pena señalar que los ingenieros de KX, comenzando por el propio Arthur Whitney, están realmente obsesionados con la eficiencia y hacen todo lo posible para aprovechar al máximo las características estándar del Q y optimizar los patrones de uso más comunes.
 

Total

KDB+ es popular entre las empresas principalmente debido a su excepcional versatilidad: sirve igualmente como base de datos en memoria, como base de datos para almacenar terabytes de datos históricos y como plataforma para análisis de datos. Debido a que el procesamiento de datos se produce directamente en la base de datos, se logra una alta velocidad de trabajo y ahorro de recursos. Un lenguaje de programación completo integrado con funciones de base de datos le permite implementar toda la pila de procesos necesarios en una plataforma, desde la recepción de datos hasta el procesamiento de solicitudes de los usuarios.
 

Para obtener más información,

Limitaciones

Una desventaja importante del KDB+/Q es el alto umbral de entrada. El lenguaje tiene una sintaxis extraña, algunas funciones están muy sobrecargadas (valor, por ejemplo, tiene alrededor de 11 casos de uso). Lo más importante es que requiere un enfoque radicalmente diferente a la hora de escribir programas. En un lenguaje vectorial, siempre debes pensar en términos de transformaciones de matrices, implementar todos los bucles a través de varias variantes de las funciones de mapa/reducción (que se llaman adverbios en Q) y nunca intentar ahorrar dinero reemplazando operaciones vectoriales con operaciones atómicas. Por ejemplo, para encontrar el índice de la enésima aparición de un elemento en una matriz, debes escribir:

1. (where element=vector)[N]  

aunque esto parece terriblemente ineficiente según los estándares de C/Java (= crea un vector booleano, donde devuelve los índices verdaderos de los elementos que contiene). Pero esta notación aclara el significado de la expresión y permite utilizar operaciones vectoriales rápidas en lugar de operaciones atómicas lentas. La diferencia conceptual entre un lenguaje vectorial y otros es comparable a la diferencia entre los enfoques de programación imperativo y funcional, y hay que estar preparado para ello.
 
Algunos usuarios tampoco están contentos con QSQL. El punto es que solo parece SQL real. En realidad, es sólo un intérprete de expresiones similares a SQL que no admite la optimización de consultas. El usuario debe escribir consultas óptimas él mismo y en Q, para las que muchos no están preparados. Por otro lado, por supuesto, siempre puedes escribir la consulta óptima tú mismo, en lugar de depender de un optimizador de caja negra.
 
Como beneficio adicional, un libro sobre Q - Q For Mortals está disponible de forma gratuita en sitio web de la empresaAllí también se recogen muchos otros materiales útiles.
 
Otra gran desventaja es el coste de la licencia. Eso supone decenas de miles de dólares al año por CPU. Sólo las grandes empresas pueden afrontar esos gastos. Recientemente, KX ha flexibilizado su política de licencias y brinda la oportunidad de pagar solo por el tiempo de uso o alquilar KDB+ en las nubes de Google y Amazon. KX también ofrece para descargar versión gratuita para fines no comerciales (Versión de 32 bits o 64 bits bajo pedido).
 

competidores

Existen bastantes bases de datos especializadas construidas sobre principios similares: en columnas, en memoria, centradas en grandes cantidades de datos. El problema es que se trata de bases de datos especializadas. Un ejemplo sorprendente es Clickhouse. Esta base de datos tiene un principio muy similar a KDB+ para almacenar datos en el disco y crear un índice; realiza algunas consultas más rápido que KDB+, aunque no de manera significativa. Pero incluso como base de datos, Clickhouse es más especializada que KDB+: análisis web frente a series temporales arbitrarias (esta diferencia es muy importante; por eso, por ejemplo, en Clickhouse no es posible utilizar el orden de registros). Pero, lo más importante, Clickhouse no tiene la versatilidad de KDB+, un lenguaje que permitiría procesar datos directamente en la base de datos, en lugar de cargarlos primero en una aplicación separada, construir expresiones SQL arbitrarias, aplicar funciones arbitrarias en una consulta, crear procesos. no relacionado con la ejecución de funciones históricas de bases de datos. Por lo tanto, es difícil comparar KDB+ con otras bases de datos; pueden ser mejores en ciertos casos de uso o simplemente mejores cuando se trata de tareas clásicas de bases de datos, pero no conozco otra herramienta igualmente efectiva y versátil para procesar datos temporales.
 

Integración de Python

Para que KDB+ sea más fácil de usar para personas que no están familiarizadas con la tecnología, KX creó bibliotecas para integrarse estrechamente con Python dentro de un solo proceso. Puede llamar a cualquier función de Python desde Q o viceversa: llamar a cualquier función de Q desde Python (en particular, expresiones QSQL). Las bibliotecas convierten, si es necesario (no siempre por motivos de eficiencia), datos del formato de un idioma al formato de otro. Como resultado, Q y Python viven en una simbiosis tan estrecha que los límites entre ellos se vuelven borrosos. Como resultado, el programador, por un lado, tiene acceso completo a numerosas bibliotecas útiles de Python y, por otro lado, recibe una base rápida para trabajar con big data integrados en Python, lo que es especialmente útil para quienes se dedican al aprendizaje automático. o modelado.
 
Trabajando con Q en 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')  

referencias

El sitio de la empresa - https://kx.com/
Sitio web para desarrolladores - https://code.kx.com/v2/
Libro Q Para Mortales (en inglés) - https://code.kx.com/q4m3/
Artículos sobre aplicaciones KDB+/Q de empleados de kx - https://code.kx.com/v2/wp/

Fuente: habr.com

Añadir un comentario