Productos secos 丨 Prueba de comparación de la base de datos de series de tiempo DolphinDB y Druid

Tanto DolphinDB como Druid son bases de datos de series de tiempo analíticas distribuidas. Aunque el primero se desarrolla en C ++ y el segundo en Java, los dos tienen mucho en común en términos de arquitectura, funciones y escenarios de aplicación. Este informe compara el rendimiento de los dos en términos de consulta SQL, importación de datos y espacio en disco.

El conjunto de datos de prueba utiliza aproximadamente 300 GB de transacciones y cotizaciones del mercado de valores de EE. UU. A través de las pruebas, encontramos:

  • La velocidad de escritura de datos de DolphinDB es aproximadamente 30 veces mayor que la de Druid .
  • La velocidad de consulta de DolphinDB es aproximadamente 10 veces mayor que la de Druid .
  • El uso de espacio estático de la base de datos DolphinDB es un 80% mayor que el de Druid , y el espacio total en disco utilizado en tiempo de ejecución es ligeramente menor que el de Druid.

1. Introducción al sistema

DolphinDB es una base de datos analítica distribuida de series de tiempo, escrita en C ++, con motor de procesamiento de datos de transmisión incorporado, motor de computación en paralelo y funciones de computación distribuida. La base de datos DolphinDB tiene un sistema de archivos distribuido integrado que admite la expansión de clústeres horizontal y vertical. Proporciona lenguajes de scripting SQL y similares a Python, no solo puede usar SQL para operar con datos, sino que también puede completar cálculos de memoria más complejos. Proporcione API en otros lenguajes de programación de uso común para facilitar la integración con aplicaciones existentes. DolphinDB puede procesar rápidamente billones de datos. Tiene un rendimiento excelente en el modelado de análisis de datos históricos y el procesamiento de datos en tiempo real en el campo financiero, así como en el procesamiento masivo de datos de sensores y análisis en tiempo real en el campo de Internet de las cosas.

Druid es un almacén de datos OLAP implementado por el lenguaje Java, que es adecuado para consultas de baja latencia e inserción de datos de un billón de niveles y análisis de datos de transmisión en tiempo real. Druid adopta tecnologías clave como distribuidas, arquitectura SN y almacenamiento en columnas, índice invertido e índice de mapa de bits, que se caracterizan por su alta disponibilidad y alta escalabilidad. Al mismo tiempo, Druid proporciona interfaces de varios idiomas y admite algunos SQL.

2. Configuración del sistema

2.1 Configuración de hardware

La configuración de hardware de esta prueba es la siguiente:

Equipo: DELL OptiPlex 7060

CPU: CPU Inter (R) Core ™ i7-8700 a 3.20 GHz, 6 núcleos y 12 subprocesos

Memoria: 32 GB

Disco duro: SSD de 256 GB, disco duro mecánico Seagate ST2000DM008-2FR102 de 1,8 TB

Sistema operativo: Ubuntu 16.04 x64

2.2 Configuración del entorno

El entorno de prueba esta vez es un clúster de varios nodos bajo un solo servidor. Establezca el número de nodos de datos de DolphinDB en 4 y establezca la memoria máxima disponible de un solo nodo de datos en 4 GB. Establezca el número de nodos Druid en 5, que son overload, broker, histórico, coordinador y middleManager. Druid almacena en caché los resultados de las consultas de forma predeterminada, lo que afecta la corrección del método de promediar a través de múltiples consultas durante la prueba, por lo que la función de caché de consultas está desactivada. Para no afectar la prueba de rendimiento de escritura de Druid, se deshabilitó la función de acumulación de Druid. Todas las demás configuraciones obedecen a la configuración predeterminada.

El archivo csv original se almacena en el disco duro. La base de datos se almacena en el SSD.

3. Conjunto de datos de prueba

Esta prueba utiliza el conjunto de datos TAQ del nivel 1 del mercado de valores de EE. UU. En agosto de 2007. El conjunto de datos TAQ se divide en 23 archivos csv a diario. El tamaño de un solo archivo varía de 7,8 G a 19,1 G. El tamaño de todo el conjunto de datos es de aproximadamente 290 G, con un total de 6.561.693.704 piezas de datos.

Los tipos de datos de cada campo en el conjunto de datos de prueba TAQ en DolphinDB y Druid son los siguientes:

3d62ba9f8bfcd07d604821c8b9ae116b.png

En Druid, el campo FECHA se designa como una columna de marca de tiempo. Otros campos se utilizan como campos de dimensión.

4. Esquema de partición de datos

En DolphinDB, se adopta la partición de combinación de código de stock + fecha, que se divide en 128 particiones según el rango del código de stock y 23 particiones según la fecha.

Druid solo admite particiones de rango de tiempo, por lo que especificamos la columna DATE como un tipo de marca de tiempo, con un día como unidad, que se divide en 23 particiones.

5. Prueba de comparación

Comparamos DolphinDB y Druid en términos de rendimiento de consultas de base de datos, rendimiento de E / S y espacio en disco.

5.1 Rendimiento de la consulta de la base de datos

El lenguaje de secuencias de comandos DolphinDB admite la sintaxis SQL y tiene funciones ampliadas para datos de series de tiempo. Druid proporciona un lenguaje basado en el formato de datos Json para consultas y también proporciona dsql para consultas SQL. Esta prueba utiliza el propio dsql de Druid.

Realizamos varias consultas SQL comunes en el conjunto de datos TAQ. Para reducir el impacto de factores accidentales en los resultados, esta prueba de rendimiento de la consulta se realizó 10 veces para cada operación de consulta, y se promedió el tiempo total y el tiempo se expresó en milisegundos. Al probar DolphinDB, usamos la declaración del temporizador para evaluar el tiempo de ejecución de la declaración SQL en el servidor. Dado que Druid no proporciona una herramienta o función para generar el tiempo de consulta, se utiliza el tiempo de ejecución impreso por la herramienta de línea de comandos del cliente dsql. En comparación con DolphinDB, el tiempo de ejecución devuelto por Druid tiene más tiempo de transmisión y visualización para los resultados de la consulta. Dado que la cantidad de datos devueltos por la consulta es muy pequeña, dsql y el servidor Druid están en el mismo nodo y el tiempo de impacto es de aproximadamente 1 ms. El tiempo de 1 ms no afecta las conclusiones de nuestra prueba, por lo que no se realiza ningún tratamiento especial.

La representación SQL de las 7 consultas se muestra en la siguiente tabla.

335ec03747bcb0a29ef29b3ba22f9372.png

Los resultados de la prueba se muestran en la siguiente tabla.

e6cc39a3384839a6d9bfcae7df9afd35.png

De los resultados, se puede ver que para casi todas las consultas, el rendimiento de DolphinDB es mejor que el de Druid, y la velocidad es de 3 a 30 veces mayor que la de Druid.

Dado que Druid solo permite la segmentación basada en marcas de tiempo, mientras que DolphinDB permite dividir los datos de varias dimensiones, se utilizan dos dimensiones de tiempo y código de stock para la partición de TAQ, por lo que la consulta debe filtrarse o agruparse según los códigos de stock. Las ventajas de DolphinDB son más obvias en las pruebas (como las pruebas 1, 3, 6 y 7).

5.2 prueba de rendimiento de E / S

Probamos el rendimiento de DolphinDB y Druid al importar un solo archivo (7.8G) y varios archivos (290.8G). Para ser justos, desactivamos la función Roll up de Druid. Los resultados de la prueba se muestran en la tabla a continuación y el tiempo está en segundos.

69edbf1e57afcf86f9c07079dc34f024.png

En las mismas circunstancias, al importar un solo archivo, el tiempo de importación de Druid es más de 16 veces mayor que el de DolphinDB. Al importar varios archivos, debido a que DolphinDB admite la importación paralela, la velocidad es más rápida que Druid. Consulte el Apéndice 2 para ver el script de importación de datos.

5.3 Prueba de espacio en disco

Después de importar datos a DolphinDB y Druid, comparamos la tasa de compresión de datos de los dos. Los resultados de la prueba se muestran en la siguiente tabla.

ed803bb15f18c4e6c14f379c5f1c1ac4.png

DolphinDB utiliza el algoritmo de compresión LZ4 para comprimir rápidamente los datos almacenados en columnas. Antes de la compresión, el tipo SYMBOL de DolphinDB usa codificación de diccionario para convertir cadenas en números enteros. En el proceso de almacenamiento de datos, Druid usa el algoritmo LZ4 para comprimir directamente la marca de tiempo y las métricas, y usa codificación de diccionario, índice de mapa de bits y mapa de bits rugiente para comprimir el campo de dimensiones. El uso de codificación de diccionario puede reducir el espacio de almacenamiento de cadenas, los índices de mapa de bits pueden realizar rápidamente operaciones lógicas a nivel de bits y la compresión del índice de mapa de bits ahorra más espacio de almacenamiento.

En esta prueba, el espacio en disco ocupado por la base de datos DolphinDB es aproximadamente un 80% mayor que el de Druid. El factor principal que causa esta diferencia es que las relaciones de compresión de los dos campos de punto flotante de BID y OFR son bastante diferentes en DolphinDB y Druid. En DolphinDB, la relación de compresión de estos dos campos es del 20%, mientras que en Druid llega al 5%. La razón es que el conjunto de datos de prueba es un conjunto de datos históricos y los datos se han ordenado según los dos campos de fecha y stock. El cambio de precio de una acción en un corto período de tiempo es muy pequeño, el número de cotizaciones únicas es muy limitado y Druid usa compresión de mapa de bits para lograr muy buenos resultados.

Aunque la relación de compresión de la base de datos de Druid es mayor y el espacio en disco estático es más pequeño, el directorio de caché de segmento se genera cuando Druid se está ejecutando y la ocupación total de espacio en disco alcanza los 65 GB. Si bien DolphinDB no requiere espacio adicional cuando se ejecuta, el espacio total en disco es ligeramente más pequeño que Druid.

6. Resumen

Las ventajas de rendimiento de DolphinDB for Druid provienen de muchos aspectos, que incluyen (1) la diferencia en el mecanismo de almacenamiento y el mecanismo de partición, (2) la diferencia en el lenguaje de desarrollo (c ++ vs java), (3) la diferencia en la gestión de memoria y ( 4) Diferencias en la implementación de algoritmos (como clasificación y hash).

En términos de partición, Druid solo admite la partición de rango de tipo de tiempo, que carece de flexibilidad en comparación con DolphinDB, que admite la partición de valores, la partición de rango, la partición de hash y la partición de listas, y cada tabla se puede particionar en función de varios campos. La granularidad de la partición de DolphinDB es más fina y no es fácil que los datos o las consultas se concentren en un nodo determinado. DolphinDB necesita escanear menos bloques de datos durante la consulta, el tiempo de respuesta es más corto y el rendimiento es mejor.

Además del rendimiento, DolphinDB es más funcional que Druid. En términos de compatibilidad con SQL, DolphinDB admite un mecanismo de función de ventana muy potente y admite la unión SQL de manera más completa. Tiene un buen soporte para la función de deslizamiento, como unión, unión de ventana y DolphinDB específico para datos de series de tiempo. DolphinDB integra bases de datos, lenguaje de programación y computación distribuida Además de las funciones regulares de consulta de bases de datos, DolphinDB también admite computación de memoria más compleja, computación distribuida y computación de flujo.

DolphinDB y Druid también son ligeramente diferentes en el modo de funcionamiento. Después de que Druid falla o se reinicia después de borrar el caché de segmento, lleva mucho tiempo recargar los datos, descomprimir cada segmento en el caché de segmento y luego consultar, la eficiencia es baja y el caché ocupará un espacio más grande. , Druid necesita esperar mucho tiempo para reiniciar y requiere más espacio.

apéndice

Apéndice 1. Configuración del entorno

(1) Configuración de DolphinDB

controller.cfg

localSite = localhost: 9919: ctl9919 
localExecutors = 3 
maxConnections = 128 
maxMemSize = 4 
webWorkerNum = 4 
workerNum = 4 
dfsReplicationFactor = 1 
dfsReplicaReliabilityLevel = 0 
enableDFS = 1 
enableHTTPS = 0

cluster.nodes

localSite, modo 
localhost: 9910: agente, agente 
localhost: 9921: DFS_NODE1, datanode 
localhost: 9922: DFS_NODE2, datanode 
localhost: 9923: DFS_NODE3, datanode 
localhost: 9924: DFS_NODE4, datanode

cluster.cfg

maxConnection = 128 
workerNum = 8 
localExecutors = 7 
webWorkerNum = 2 
maxMemSize = 4

agent.cfg

workerNum = 3 
localExecutors = 2 
maxMemSize = 4 
localSite = localhost: 9910: agent 
controllerSite = localhost: 9919: ctl9919

(2) Configuración de druida

_común

# Zookeeper 
druid.zk.service.host = zk.host.ip 
druid.zk.paths.base = / druid 
# Almacenamiento de metadatos 
druid.metadata.storage.type = mysql 
druid.metadata.storage.connector.connectURI = jdbc: mysql : //db.example.com: 3306 / druid 
# Almacenamiento profundo 
druid.storage.type = local 
druid.storage.storageDirectory = var / druid / segmentos 
# 
Registros de servicios de indexación druid.indexer.logs.type = file 
druid.indexer. logs.directory = var / druid / indexing-logs

corredor:

Xms24g 
Xmx24g 
XX: MaxDirectMemorySize = 4096m 

# Subprocesos del servidor HTTP 
druid.broker.http.numConnections = 5 
druid.server.http.numThreads = 25 

# Procesamiento de subprocesos y búferes 
druid.processing.buffer.sizeBytes = 
7num47483648 druid.processing. 

# Query cache 
druid.broker.cache.useCache = false 
druid.broker.cache.populateCache = false 

coordinator: 
Xms3g 
Xmx3g 

historical: 
Xms8g 
Xmx8g 

# HTTP server threads 
druid.server.http.numThreads = 25 

# Procesando threads y búferes 
druid.processing .buffer.sizeBytes = 2147483648 
druid.processing.numThreads = 7

# Almacenamiento de segmentos 
druid.segmentCache.locations = [{"ruta": "var / druid / segmento-cache", "maxSize": 0}] 
druid.server.maxSize = 

130000000000 druid.historical.cache.useCache = falso 
druida. historic.cache.populateCache = false 

middleManager: 
Xms64m 
Xmx64m 

# Número de tareas por middleManager 
druid.worker.capacity = 3 

# Subprocesos del servidor HTTP 
druid.server.http.numThreads = 25 

# Procesamiento de subprocesos y búferes en Peones 
druid.indexer.fork. property.druid.processing.buffer.sizeBytes = 4147483648 
druid.indexer.fork.property.druid.processing.numThreads = 2

sobrecarga:

Xms3g 
Xmx3g

Apéndice 2. Script de importación de datos

Base de datos DolphinDB 脚本 :

if (existeDatabase ("dfs: // TAQ")) 
dropDatabase ("dfs: // TAQ") 

db = database ("/ Druid / table", SEQ, 4) 
t = loadTextEx (db, 'table',, " /data/data/TAQ/TAQ20070801.csv ") 
t = seleccionar recuento (*) como ct de t agrupar por símbolo 
cubos = cutPoints (símbolo ejecutivo de t, 128) 
cubos [tamaño (cubos) -1] =` ZZZZZ 
t1 = tabla (depósitos como depósito) 
t1.saveText ("/ data / data / TAQ / buckets.txt") 

db1 = database ("", VALUE, 2007.08.01..2007.09.01) 
partición = loadText ("/ data / data / buckets.txt ") 
particiones = exec * de la partición 
db2 = base de datos (" ", RANGO, particiones) 
db = database (" dfs: // TAQ ", HIER, [db1, db2])
db.createPartitionedTable (table (100: 0, `symbol`date`time`bid`ofr`bidsiz`ofrsiz`mode`ex`mmid, [SYMBOL, DATE, SECOND, DOUBLE, DOUBLE, INT, INT, INT, CHAR, SYMBOL]), `quotes,` date`symbol) 

def loadJob () { 
filenames = exec filename from files ('/ data / data / TAQ') 
db = database ("dfs: // TAQ") 
fildeir = '/ data / data / TAQ ' 
para (fname en los nombres de archivo) { 
jobId = fname.strReplace (". csv", "") 
jobName = jobId  
submitJob (jobId, jobName, loadTextEx {db, "quotes", `date`symbol, fileir +' / '+ fname}) 
} 
} 
loadJob () 
select * from getRecentJobs () 
TAQ = loadTable ("dfs: // TAQ", "comillas");

Guión de druida:

{ 
"type": "index", 
"spec": { 
"dataSchema": { 
"dataSource": "TAQ", 
"parser": { 
"type": "string", 
"parseSpec": { 
"format": " csv ", 
" dimensionSpec ": { 
" dimension ": [ 
" TIME ", 
" SYMBOL ", 
{" name ":" BID "," type ":" double "}, 
{" name ":" OFR "," type ":" doble "}, 
{" nombre ":" BIDSIZ "," tipo ":" int "}, 
{" nombre ":" OFRSIZ "," tipo ":" int "}, 
"MODE ", 
" EX ", 
" MMID " 
] 
}, 
" timestampSpec ": { 
" columna ":" FECHA ", 
" formato ":" aaaaMMdd " 
}, 
" columnas ": [" SÍMBOLO ", 
" FECHA ", 
" HORA ", 
" BID ",
"OFR", 
"BIDSIZ", 
"OFRSIZ", 
"MODE", 
"EX", 
"MMID"] 
} 
}, 
"metricsSpec": [], 
"granularitySpec": { 
"tipo": "uniforme", 
"segmentoGranularidad" : "día", 
"queryGranularity": "ninguno", 
"intervalos": ["2007-08-01 / 2007-09-01"], 
"rollup": false 
} 
}, 
"ioConfig": { 
"type": "index", 
"firehose": { 
"type": "local", 
"baseDir": "/ data / data /", 
"filter ":" TAQ.csv " 
}, 
" appendToExisting ": false 
}, 
" tuningConfig ": { 
" type ":" index ", 
" targetPartitionSize ": 5000000, 
"maxRowsInMemory": 25000, 
"forceExtendableShardSpecs": true
} 
} 
}


Supongo que te gusta

Origin blog.51cto.com/15022783/2577739
Recomendado
Clasificación