Tengo un conjunto de datos de 1 minuto de 1000 acciones desde 1998, que totalizan alrededor de (2012-1998)*(365*24*60)*1000 = 7.3 Billion
filas.
La mayoría de las veces (99,9%) solo realizaré solicitudes de lectura .
¿Cuál es la mejor manera de almacenar estos datos en una base de datos?
- 1 mesa grande con 7.300 millones de filas
- 1000 tablas (una para cada símbolo de acciones) con 7,3 millones de filas cada una?
- alguna recomendación de motor de base de datos? (Estoy planeando usar MySQL de Amazon RDS)
No estoy acostumbrado a trabajar con conjuntos de datos tan grandes, por lo que esta es una excelente oportunidad para aprender. Agradeceré mucho tu ayuda y consejo.
Editar:
Esta es una fila de muestra:
'XX', 20041208, 938, 43.7444, 43.7541, 43.735, 43.7444, 35116.7, 1, 0, 0
La columna 1 es el símbolo bursátil, la columna 2 es la fecha, la columna 3 es el minuto, el resto son precios de apertura-alto-bajo-cierre, volumen y 3 columnas enteras.
La mayoría de las consultas serán como "Dame los precios de AAPL entre el 12 de abril de 2012 a las 12:15 y el 13 de abril de 2012 a las 12:52".
Acerca del hardware: planeo usar Amazon RDS, así que soy flexible en eso
Respuestas:
Cuéntenos sobre las consultas y su entorno de hardware.
Me sentiría muy, muy tentado a usar NoSQL , usando Hadoop o algo similar, siempre que pueda aprovechar el paralelismo.
Actualizar
De acuerdo, ¿por qué?
En primer lugar, observe que le pregunté sobre las consultas. No puede, y ciertamente no podemos, responder estas preguntas sin saber cómo es la carga de trabajo. (Coincidentemente tendré un artículo sobre esto que aparecerá pronto, pero no puedo vincularlo hoy). Pero la escala del problema me hace pensar en alejarme de una Big Old Database porque
Mi experiencia con sistemas similares sugiere que el acceso será secuencial grande (calculando algún tipo de análisis de series de tiempo) o minería de datos muy, muy flexible (OLAP). Los datos secuenciales se pueden manejar mejor y más rápido de forma secuencial; OLAP significa calcular montones de índices, lo que o bien llevará mucho tiempo o mucho espacio.
Sin embargo, si está haciendo lo que son efectivamente grandes ejecuciones contra muchos datos en un mundo OLAP, lo mejor sería un enfoque orientado a columnas.
Si desea realizar consultas aleatorias, especialmente comparaciones cruzadas, un sistema Hadoop puede resultar eficaz. ¿Por qué? Porque
Pero el hecho es que, hasta que sepamos su carga de trabajo, es imposible decir algo definitivo.
fuente
Entonces, las bases de datos son para situaciones en las que tiene un esquema grande y complicado que cambia constantemente. Solo tiene una "tabla" con un puñado de campos numéricos simples. Lo haría de esta manera:
Prepare una estructura C / C ++ para mantener el formato de registro:
Luego calcule sizeof (StockPrice [N]) donde N es el número de registros. (En un sistema de 64 bits) Solo debería ser de unos cientos de conciertos y caber en un disco duro de $ 50.
Luego trunque un archivo a ese tamaño y mmap (en Linux, o use CreateFileMapping en Windows) en la memoria:
Envíe el puntero mmaped a StockPrice * y pase sus datos completando la matriz. Cierre el mmap y ahora tendrá sus datos en una gran matriz binaria en un archivo que puede volver a mmapear más tarde.
Ahora puede volver a mmap como solo lectura desde cualquier programa y sus datos estarán disponibles:
Así que ahora puede tratarlo como una matriz de estructuras en memoria. Puede crear varios tipos de estructuras de datos de índice según cuáles sean sus "consultas". El kernel se ocupará de intercambiar los datos hacia / desde el disco de forma transparente, por lo que será increíblemente rápido.
Si espera tener un patrón de acceso determinado (por ejemplo, una fecha contigua), es mejor ordenar la matriz en ese orden para que llegue al disco secuencialmente.
fuente
Almacenar una vez y leer muchas veces datos numéricos basados en el tiempo es un caso de uso denominado "serie temporal". Otras series de tiempo comunes son los datos de sensores en Internet de las cosas, las estadísticas de monitoreo del servidor, los eventos de aplicaciones, etc.
Esta pregunta se hizo en 2012 y, desde entonces, varios motores de bases de datos han estado desarrollando funciones específicamente para administrar series de tiempo. He tenido excelentes resultados con InfluxDB , que es de código abierto, escrito en Go y con licencia del MIT.
InfluxDB se ha optimizado específicamente para almacenar y consultar datos de series de tiempo. Mucho más que Cassandra , que a menudo se promociona como excelente para almacenar series de tiempo:
La optimización para series de tiempo implicaba ciertas compensaciones. Por ejemplo:
En benchmarks de código abierto ,
Las consultas también son muy sencillas. Si sus filas se ven así
<symbol, timestamp, open, high, low, close, volume>
, con InfluxDB puede almacenar solo eso y luego consultar fácilmente. Diga, durante los últimos 10 minutos de datos:No hay ID, claves ni uniones que realizar. Puedes hacer muchas agregaciones interesantes . No tiene que dividir verticalmente la tabla como con PostgreSQL , o contorsionar su esquema en matrices de segundos como con MongoDB . Además, InfluxDB se comprime muy bien, mientras que PostgreSQL no podrá realizar ninguna compresión en el tipo de datos que tiene .
fuente
Bien, esto está algo alejado de las otras respuestas, pero ... me parece que si tiene los datos en un sistema de archivos (un stock por archivo, tal vez) con un tamaño de registro fijo, puede obtener los datos De Verdad fácil: dada una consulta para un stock y un rango de tiempo en particular, puede buscar el lugar correcto, obtener todos los datos que necesita (sabrá exactamente cuántos bytes), transformar los datos en el formato que necesita (que podría sea muy rápido dependiendo de su formato de almacenamiento) y ya no está.
No sé nada sobre el almacenamiento de Amazon, pero si no tiene nada como acceso directo a archivos, básicamente podría tener blobs; necesitaría equilibrar blobs grandes (menos registros, pero probablemente leyendo más datos de los que necesita cada uno time) con pequeñas manchas (más registros dan más sobrecarga y probablemente más solicitudes para acceder a ellos, pero cada vez se devuelven menos datos inútiles).
A continuación, agregue el almacenamiento en caché (le sugiero que, por ejemplo, asigne diferentes valores a diferentes servidores para manejar), y puede prácticamente servir desde la memoria. Si puede permitirse suficiente memoria en suficientes servidores, omita la parte de "carga a pedido" y simplemente cargue todos los archivos al inicio. Eso simplificaría las cosas, a costa de una puesta en marcha más lenta (lo que obviamente afecta la conmutación por error, a menos que pueda permitirse tener siempre dos servidores para cualquier stock en particular, lo que sería útil).
Tenga en cuenta que no necesita almacenar el símbolo de cotización, la fecha o el minuto de cada registro, porque están implícitos en el archivo que está cargando y la posición dentro del archivo. También debe considerar qué precisión necesita para cada valor y cómo almacenar eso de manera eficiente: ha dado 6SF en su pregunta, que podría almacenar en 20 bits. Potencialmente almacene tres enteros de 20 bits en 64 bits de almacenamiento: léalo como un
long
(o cualquiera que sea su valor entero de 64 bits) y use enmascaramiento / desplazamiento para volverlo a tres enteros. Necesitará saber qué escala usar, por supuesto, que probablemente podría codificar en los 4 bits de repuesto, si no puede hacerlo constante.No ha dicho cómo son las otras tres columnas enteras, pero si pudiera salirse con 64 bits para esas tres también, podría almacenar un registro completo en 16 bytes. Eso es solo ~ 110GB para toda la base de datos, que en realidad no es mucho ...
EDITAR: La otra cosa a considerar es que presumiblemente las acciones no cambian durante el fin de semana, o de hecho durante la noche. Si el mercado de valores solo está abierto 8 horas al día, 5 días a la semana, entonces solo necesita 40 valores por semana en lugar de 168. En ese momento, podría terminar con solo alrededor de 28 GB de datos en sus archivos ... lo que suena mucho más pequeño de lo que probablemente pensabas originalmente. Tener tantos datos en la memoria es muy razonable.
EDITAR: Creo que me he perdido la explicación de por qué este enfoque encaja bien aquí: tiene un aspecto muy predecible para una gran parte de sus datos: el indicador de cotización, la fecha y la hora. Al expresar el ticker una vez (como nombre de archivo) y dejar la fecha / hora totalmente implícita en la posición de los datos, está eliminando un montón de trabajo. Es un poco como la diferencia entre una
String[]
y unaMap<Integer, String>
- a sabiendas de que su índice de la matriz siempre empieza en 0 y sube en incrementos de 1 hasta la longitud de la matriz permite un acceso rápido y un almacenamiento más eficiente.fuente
Tengo entendido que HDF5 se diseñó específicamente con el almacenamiento de series de tiempo de datos de existencias como una aplicación potencial. Otros apiladores han demostrado que el HDF5 es bueno para grandes cantidades de datos: cromosomas , física .
fuente
Aquí hay un intento de crear un servidor de datos de mercado sobre la base de datos de Microsoft SQL Server 2012 que debería ser bueno para el análisis OLAP, un proyecto de código abierto gratuito:
http://github.com/kriasoft/market-data
fuente
Primero, no hay 365 días comerciales en el año, con feriados 52 fines de semana (104) = digamos 250 x las horas reales del día, el mercado está abierto como alguien dijo, y usar el símbolo como clave principal no es una buena idea dado que los símbolos cambian, use un k_equity_id (numérico) con un símbolo (char) ya que los símbolos pueden ser como este A, o GAC-DB-B.TO, luego en sus tablas de datos de información de precios, tiene, por lo que su estimación de 7.3 mil millones está muy sobrecalculado, ya que son solo alrededor de 1,7 millones de filas por símbolo durante 14 años.
k_equity_id k_date k_minute
y para la tabla EOD (que se verá 1000 veces más que los otros datos)
k_equity_id k_date
En segundo lugar, no almacene sus datos de OHLC por minuto en la misma tabla de base de datos que la tabla de EOD (al final del día), ya que cualquiera que desee ver un pnf, o gráfico de líneas, durante un período de un año, no tiene interés en el by la información del minuto.
fuente
Permítame recomendarle que eche un vistazo a apache solr , que creo que sería ideal para su problema particular. Básicamente, primero indexaría sus datos (cada fila es un "documento"). Solr está optimizado para la búsqueda y admite de forma nativa consultas de rango en fechas. Tu consulta nominal,
"Give me the prices of AAPL between April 12 2012 12:15 and April 13 2012 12:52"
se traduciría a algo como:
Suponiendo que "stock" es el nombre del stock y "date" es un "DateField" creado a partir de las columnas "fecha" y "minuto" de sus datos de entrada sobre la indexación. Solr es increíblemente flexible y realmente no puedo decir lo suficiente sobre él. Entonces, por ejemplo, si necesita mantener los campos en los datos originales, probablemente pueda encontrar una manera de crear dinámicamente el "DateField" como parte de la consulta (o filtro).
fuente
Creo que cualquier RDBMS importante manejaría esto. A nivel atómico, una tabla única con la partición correcta parece razonable (la partición se basa en el uso de datos, si es fija, probablemente sea símbolo o fecha).
También puede considerar la creación de tablas agregadas para un acceso más rápido por encima del nivel atómico. Por ejemplo, si sus datos son por día, pero a menudo obtiene datos a nivel de semana o incluso de mes, entonces esto puede calcularse previamente en una tabla agregada. En algunas bases de datos, esto se puede hacer a través de una vista almacenada en caché (varios nombres para diferentes soluciones de base de datos, pero básicamente es una vista de los datos atómicos, pero una vez que se ejecuta, la vista se almacena en caché / endurece en una tabla temporal fija) que se consulta para consultas coincidentes subsecuentes Esto se puede eliminar a intervalos para liberar memoria / espacio en disco).
Supongo que podríamos ayudarlo más con alguna idea sobre el uso de datos.
fuente
Debe comparar las soluciones lentas con un modelo simple optimizado en memoria. Sin comprimir cabe en un servidor RAM de 256 GB. Una instantánea cabe en 32 K y simplemente la indexa posicionalmente en fecha y hora y stock. Luego, puede hacer instantáneas especializadas, ya que abrir una a menudo equivale a cerrar la anterior.
[editar] ¿Por qué crees que tiene sentido usar una base de datos (rdbms o nosql)? Estos datos no cambian y caben en la memoria. Ese no es un caso de uso en el que un dbms pueda agregar valor.
fuente
Si tiene el hardware, le recomiendo MySQL Cluster . Obtiene la interfaz MySQL / RDBMS con la que está tan familiarizado y obtiene escrituras rápidas y paralelas. Las lecturas serán más lentas que MySQL normal debido a la latencia de la red, pero tiene la ventaja de poder paralelizar consultas y lecturas debido a la forma en que MySQL Cluster y el motor de almacenamiento NDB funcionan.
Sin embargo, asegúrese de tener suficientes máquinas MySQL Cluster y suficiente memoria / RAM para cada una de ellas: MySQL Cluster es una arquitectura de base de datos muy orientada a la memoria.
O Redis , si no le importa una interfaz clave-valor / NoSQL para sus lecturas / escrituras. Asegúrese de que Redis tenga suficiente memoria: es súper rápido para lecturas y escrituras, puede hacer consultas básicas con él (aunque no es RDBMS) pero también es una base de datos en memoria.
Como han dicho otros, saber más sobre las consultas que ejecutará le ayudará.
fuente
Querrá que los datos se almacenen en una tabla / base de datos en columnas . Los sistemas de bases de datos como Vertica y Greenplum son bases de datos en columnas, y creo que SQL Server ahora permite tablas en columnas. Estos son extremadamente eficientes para
SELECT
trabajar con conjuntos de datos muy grandes. También son eficientes para importar grandes conjuntos de datos.Una base de datos en columnas gratuita es MonetDB .
fuente
Si su caso de uso es leer filas sin agregación, puede usar el clúster Aerospike. Está en la base de datos de la memoria con soporte del sistema de archivos para la persistencia. También está optimizado para SSD.
Si su caso de uso necesita datos agregados, elija el clúster de base de datos de Mongo con fragmentación de rango de fechas. Puede agrupar los datos del tornillo de banco del año en fragmentos.
fuente