Escanear mil millones de filas en una base de datos ultrarrápida

9

Antecedentes

Una base de datos local contiene casi 1.300 millones de filas únicas. Cada fila está asociada indirectamente con una latitud y longitud (ubicación) específicas. Cada fila tiene un sello de fecha.

Caso de uso

El problema es el siguiente:

  1. El usuario establece una fecha de inicio / finalización y un rango de valores (por ejemplo, 100 a 105).
  2. El sistema reúne todas las filas que coinciden con la fecha dada, agrupadas por ubicación.
  3. El sistema realiza determina las ubicaciones que, durante esas fechas, tienen una probabilidad estadística de caer en el rango de valores dado.
  4. El sistema muestra todas las ubicaciones coincidentes para el usuario.

Este es un problema de velocidad y escala.

Pregunta

¿Cuál es la arquitectura de solución menos costosa que pueda imaginar que permitiría que dicho sistema recupere resultados para los usuarios en menos de cinco segundos?

Sistema actual

El entorno es actualmente:

  • PostgreSQL 8.4 (la actualización es posible; cambiar de base de datos no es una opción)
  • R y PL / R
  • XFS
  • WD VelociRaptor
  • 8 GB de RAM (Corsair G.Skill; 1.3 GHz)
  • Quad Core Genuino Intel 7 (2.8 GHz)
  • Ubuntu 10.10

Las actualizaciones de hardware son aceptables.

Actualización: estructura de la base de datos

Los miles de millones de filas están en una tabla similar a:

id | taken | location_id | category | value1 | value2 | value3
  • id: clave principal
  • tomado - Fecha asignada a la fila
  • location_id - Referencia a la latitud / longitud
  • categoría: una descripción de los datos
  • valor1 .. 3 - Los otros valores que el usuario puede consultar

La takencolumna suele tener fechas consecutivas por location_id, a veces cada ubicación tiene datos de 1800 a 2010 (aproximadamente 77,000 fechas, muchas de ellas duplicadas ya que cada ubicación tiene datos en el mismo rango de fechas).

Hay siete categorías y las tablas ya están divididas por categoría (usando tablas secundarias). Cada categoría contiene ~ 190 millones de filas. En el futuro cercano, el número de filas por categoría superará los mil millones.

Hay aproximadamente 20,000 ubicaciones y 70,000 ciudades. Las ubicaciones están correlacionadas con la ciudad por latitud y longitud. Asignar cada ubicación a una ciudad en particular significa encontrar los límites de la ciudad, lo cual no es una tarea trivial.

Ideas

Algunas ideas que tengo incluyen:

  • Encuentre un servicio en la nube para alojar la base de datos.
  • Cree una banda de incursión SSD (excelente video).
  • Cree una tabla que amalgame todas las ubicaciones por ciudad (cálculo previo).

¡Gracias!

Dave Jarvis
fuente
10
"cambiar bases de datos no es una opción", eso elimina la mayoría de las soluciones. ¡buena suerte!
Steven A. Lowe
1
Es difícil decirlo sin más información sobre qué está haciendo exactamente con esos registros. Además, ¿está buscando el peor caso de 5 segundos (lo que probablemente significa que cada registro examinado y cero ubicaciones coinciden)?
Guy Sirton
2
@Dave: ¿Cuánto tiempo lleva el sistema actual? ¿El sistema actual usa PostGIS ? ¿Es location_idun geographyo geometry, o se refiere a una segunda tabla? ¿Está location_idindexada la columna?
rwong
1
@ Thorbjørn y @Darknight: en la sección de ideas enumero el cálculo previo, lo que reduciría los datos a un valor por ciudad por día (por categoría). El cálculo podría repetirse anualmente, o incluso mensualmente, supongo. Este era mi plan si no hubiera otras posibilidades (los cálculos probablemente tomarán semanas).
Dave Jarvis
1
@Dave, muchas posibilidades, pero la pregunta es qué es relevante para ti. ¿Has investigado dónde están los cuellos de botella actuales?

Respuestas:

12

Lo más importante es estar absolutamente seguro de dónde está ahora el cuello de botella para un número determinado de solicitudes representativas, ya que no puede cambiar las bases de datos.

Si realiza escaneos completos de la tabla, necesita índices apropiados.

Si espera en E / S, necesita más memoria para el almacenamiento en caché (Jeff Atwood mencionó recientemente que los sistemas de 24 Gb eran accesibles en sistemas de escritorio).

Si espera en la CPU, necesita ver si sus cálculos pueden optimizarse.

Esto requiere un sombrero DBA puntiagudo y un sombrero de sistema operativo, pero vale la pena para asegurarse de que está ladrando el árbol correcto.


fuente
Cada vez que lo corta y corta en dados, incluso si cada fila toma solo 100 bytes, 1.3 billones de filas = 121 GB. Con todos sus índices, etc., estoy seguro de que será mucho más. En una sola caja, será lento a menos que tenga un hardware serio alrededor de SSD + Toneladas de ram. Una forma más barata es escalar a través de cajas.
Subu Sankara Subramanian
44
@Subu, ¿quieres ir distribuido? Ahora tiene dos problemas ...
Je - con lo que estoy de acuerdo :) ¡Pero es más barato!
Subu Sankara Subramanian
@ Thorbjørn: Gracias por su tiempo y toda su ayuda. Creo que reduciré el conjunto de datos a 25 millones de filas por categoría y luego aplicaré índices en la fecha. Eso debería reducir el escaneo a ~ 70000 filas (por día, con un límite de dos semanas para el rango), lo que debería ser bastante ágil.
Dave Jarvis
@Dave, aún necesitas saber dónde están tus cuellos de botella. Aprende mientras no tengas que hacerlo.
4

¿Qué hay de dividir la tabla en varias partes ubicadas en diferentes hosts en función del sello de fecha? Esto es escalable horizontalmente, y siempre que tenga un número suficiente de cuadros, podría escribir un pequeño motor de agregación sobre estas configuraciones.

Si ve que el sello de fecha está cambiando demasiado, entonces podría realizar una partición en función de las ubicaciones, nuevamente escalable horizontalmente. (¡Ojalá no agreguen muchas más latitudes / longitudes!)

Subu Sankara Subramanian
fuente
Gracias por las ideas. Hay potencialmente 77,066 fechas, y se agregarán nuevas fechas en el futuro. Tengo una sola maquina. Hay 20,000 ubicaciones, pero dividirlas por ubicación no ayudaría porque los datos a analizar abarcan todas las ubicaciones.
Dave Jarvis
¿Y cómo es el uso de la nube diferente de la solución anterior?
Chani
Esto es lo que pensé también. Algún tipo de partición horizontal para que la búsqueda pueda realizarse en paralelo en todas las particiones.
davidk01
Dividir en el día probablemente sería lo más útil, resultando en 2562 tablas separadas (366 días x 7 categorías).
Dave Jarvis
4

El peor de los casos es que el rango de fechas cubra todas las fechas en su base de datos.

Está buscando leer 1.300 millones de registros y hacer algún tipo de análisis en cada registro frente a los valores ingresados, en una máquina física, en menos de 5 segundos. El resultado puede ser todas las ubicaciones o ninguna: no sabe nada de antemano.

Dados estos parámetros, diría que probablemente imposible.

Basta con mirar su disco duro: la velocidad máxima sostenida es inferior a 150 MB / s. Leer 1.300 millones de registros llevará más de 5 segundos. En cuanto a la CPU, no podrá realizar ningún tipo de análisis estadístico de 1.300 millones de registros en 5 segundos.

Su única esperanza (tm :-)) es encontrar algún tipo de función de búsqueda basada en los valores ingresados ​​por el usuario que reducirá la búsqueda (en unos pocos órdenes de magnitud). Puede calcular esta función de búsqueda sin conexión. Sin saber más sobre los criterios de coincidencia exacta, no creo que nadie pueda decirle cómo hacerlo, pero un ejemplo sería dividir el rango de valores en un intervalo discreto y crear una búsqueda que le brinde todos los registros en ese intervalo. Siempre que el intervalo sea lo suficientemente pequeño, puede hacer un trabajo real en él, por ejemplo, eliminar las entradas que no coinciden con el valor introducido por el usuario. Básicamente intercambiando espacio por tiempo.

Es posible conservar todos los registros (o al menos la parte importante) en la memoria. Probablemente no en 8GB. Esto al menos eliminará la porción de E / S del disco, aunque incluso el ancho de banda de la memoria puede ser insuficiente para escanear todo en 5 segundos. En cualquier caso, esta es otra técnica para acelerar este tipo de aplicaciones (combinar con mi sugerencia anterior).

Menciona el uso de un servicio en la nube. Sí, si paga suficiente CPU e IO muscular y particiona su base de datos en muchos servidores, puede forzar / dividir y conquistarla.

Guy Sirton
fuente
Gracias por la respuesta. Las actualizaciones de hardware son una consideración, según las ideas que enumeré. Una solución de menos de $ 750 USD sería ideal.
Dave Jarvis
2

Segundo comentario de rwong a la pregunta: PostgreSQL ofrece tipos y herramientas de índices apropiados (índices GIST, índices GIN, Postgis, tipos geométricos) de tal manera que los datos relacionados con la geodata y la fecha y hora se puedan buscar a lo largo de esos criterios sin muchos problemas.

Si sus consultas sobre estos criterios toman segundos, probablemente significa que no se están utilizando dichos índices. ¿Puedes confirmar que has investigado esto según corresponda?

Denis de Bernardy
fuente
Gracias. Las siete tablas secundarias se agrupan en la ubicación, la fecha y la categoría mediante un btree. Investigué los índices GIN el año pasado y no me ayudaron (o no lo harían), según recuerdo.
Dave Jarvis
2
La ubicación de indexación basada en B-Tree no es lo más útil teniendo en cuenta el tipo de búsquedas que está buscando. Necesita un índice invertido que funcione con los operadores necesarios, que en el caso de Postgis generalmente significa GIST. Es posible que desee resaltar algunas de las consultas lentas ...
Denis de Bernardy
1

Dado que usa PostgreSQL y los datos de latitud / longitud, definitivamente también debe usar PostGIS, de esa manera puede agregar un índice espacial GiST a su base de datos para ayudar a acelerar las cosas.

Tengo una tabla de este tipo (con 350k filas) con una configuración mucho más pequeña que la suya (2 núcleos y apenas 2Gb de RAM) pero las búsquedas toman menos de un segundo.

picos salvajes
fuente
0

Tal vez podría romper un modelo relacional como hizo Essbase con su arquitectura OLAP: Essbase Wikipedia

Lo que quiero decir es crear una tabla por ciudad, terminando así con más de 1000 tablas. No una mesa como usted sugirió, sino muchas. Indice cada tabla por fecha y ubicación. Muchas tablas, muchos índices -> más rápido.

mihaela
fuente
Gracias por la nota Hay más de 70,000 ciudades, y muchos valores diferentes de latitud / longitud caen dentro de un área específica de la ciudad.
Dave Jarvis
@Dave: ¿puedes construir un diagrama de voronoi para ciudades y clasificar los valores de lat / lon en teselaciones? (es decir, si suena desordenado, déjelo ser). Luego, durante la búsqueda, buscará todas las ciudades cuya teselación toque los rangos lat / lon de la consulta. Si la teselación de voronoi es demasiado lenta, puede valer la pena probar cajas cuadradas (por ejemplo, 5 grados de ancho x 5 grados de largo).
rwong
0

En cuanto a su idea de encontrar un servicio en la nube para alojar la base de datos, ¿ya se ha encontrado con SimpleGeo ? Simplemente cortan la cinta en un servicio de almacenamiento que aparentemente está "específicamente ajustado para almacenar y consultar datos de ubicación realmente, muy rápido", aunque el costo de almacenar y consultar en más de mil millones de filas podría hacer que este enfoque sea inviable.

IanI
fuente
-2

Esperas que una bicicleta corra en la carretera. actualmente está buscando una solución para abordar este problema solamente, no está previendo el problema, ¿qué pasa si tiene 2 mil millones de registros? la escalabilidad debe ser abordada. La respuesta es simple uso de bases de datos de objetos. por ejemplo, caché Intersystems

y créeme, no soy de un sistema intermedio ;-)

anerjan
fuente