2010-02-04 18 views
7

Actualmente estamos considerando un cambio de Postgres a CouchDB para una aplicación de monitoreo de uso. Algunos números:Estructura de documentos recomendada para CouchDB

Aproximadamente 2000 conexiones, sondeadas cada 5 minutos, para aproximadamente 600,000 nuevas filas por día. En Postgres, almacenamos estos datos, dividida por día:

t_usage {service_id, fecha y hora, data_in, data_out}
t_usage_20100101 hereda t_usage.
t_usage_20100102 hereda t_usage. etc.

Escribimos datos con un proceso almacenado optimista que supone que la partición existe y la crea si es necesario. Podemos insertar muy rápidamente.

Para la lectura de los datos, nuestros casos de uso, en orden de importancia y los resultados actuales son:
* Servicio individual, Día Individual Uso: Buen Rendimiento
* Servicios Múltiples, Mes Uso: Bajo rendimiento
* Individual servicio, mes de uso: bajo rendimiento
* Servicios múltiples, múltiples Meses: Rendimiento Muy pobre
* Servicios múltiples, Single Day: buen rendimiento

Esto tiene sentido porque las particiones están optimizados para el día, que es de lejos nuestro la mayoría imp caso de uso importante. Sin embargo, estamos buscando métodos para mejorar los requisitos secundarios.

A menudo necesitamos parametrizar la consulta por horas también, por ejemplo, solo dando resultados entre 8am y 6pm, por lo que las tablas de resumen son de uso limitado. (Estos parámetros cambian con la frecuencia suficiente que la creación de múltiples tablas de resumen de datos es prohibitiva).

Con ese trasfondo, la primera pregunta es: ¿Es CouchDB apropiado para esta información? Si es así, dados los casos de uso anteriores, ¿cuál sería el mejor modelo de los datos en documentos CouchDB? Algunas opciones que he puesto juntos hasta ahora, que estamos en el proceso de evaluación comparativa son (_id, _rev excluido):

un documento por conexión por día

{ 
    service_id:555 
    day:20100101 
    usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}} 
} 

Aproximadamente 60.000 nuevos documentos al mes. La mayoría de los datos nuevos serían actualizaciones de documentos existentes, en lugar de nuevos documentos.

(Aquí, los objetos en uso están codificados en la marca de tiempo de la encuesta, y los valores entran y salen).

un documento por conexión por mes

{ 
    service_id:555 
    month:201001 
    usage: {1265248762: {in:584,out:11342}, 1265249062: {in:94,out:1242}} 
} 

Aproximadamente 2.000 documentos nuevos al mes. Se requieren actualizaciones moderadas a los documentos existentes.

un documento por la fila de los datos recogidos

{ 
    service_id:555 
    timestamp:1265248762 
    in:584 
    out:11342 
} 
{ 
    service_id:555 
    timestamp:1265249062 
    in:94 
    out:1242 
} 

Aproximadamente 15 millones de nuevos documentos al mes. Todos los datos serían una inserción de un nuevo documento. Inserciones más rápidas, pero tengo dudas sobre lo eficiente que será después de un año o 2 años con cientos de millones de documentos. El archivo IO parecería prohibitivo (aunque soy el primero en admitir que no entiendo completamente la mecánica de esto).

Estoy tratando de enfocar esto de una manera orientada a documentos, aunque romper el hábito RDMS es difícil :) El hecho de que solo se pueden parametrizar vistas mínimamente también me tiene un poco preocupado. Dicho esto, ¿cuál de los anteriores sería el más apropiado? ¿Hay otros formatos que no he considerado que tendrán un mejor rendimiento?

Gracias de antemano,

Jamie.

Respuesta

10

No creo que sea una idea horrible.

Consideremos su escenario Conexión/Mes.

Dado que una entrada es ~ 40 (que es generosa) caracteres de largo, y obtiene ~ 8,200 entradas por mes, el tamaño del documento final será ~ 350K de largo al final del mes.

Eso significa que, a medida que avanzas, estarás leyendo y escribiendo 2000 documentos 350K cada 5 minutos.

I/O sabio, esto es menos de 6 MB/s, teniendo en cuenta leer y escribir, promediado para el período de tiempo de 5 m. Eso está bien incluso en hardware de gama baja hoy.

Sin embargo, hay otro problema. Cuando almacene ese documento, Couch evaluará su contenido para construir su vista, por lo que Couch analizará 350 mil documentos. Mi temor es que (en el último control, pero ha pasado un tiempo). No creo que Couch haya escalado bien en los núcleos de la CPU, por lo que esto podría fijar fácilmente el único núcleo de la CPU que usará Couch. Me gustaría esperar que Couch pueda leer, analizar y procesar 2 MB/s, pero francamente no lo sé. Con todos sus beneficios, erlang no es el mejor arnés en un lenguaje de computadora en línea recta.

La última preocupación es mantenerse al día con la base de datos. Esto escribirá 700 MB cada 5 minutos a fin de mes. Con la arquitectura Couchs (solo agregar), estará escribiendo 700MB de datos cada 5 min, que es 8.1 GB por hora, y 201 GB después de 24 horas.

Después de la compresión de DB, se reduce a 700MB (durante un solo mes), pero durante ese proceso, ese archivo se pondrá grande, y bastante rápido.

En el lado de recuperación, estos documentos grandes no me asustan. Cargando un documento 350K JSON, sí, es grande, pero no es tan grande, no está en un hardware moderno. Hay avatares en los tablones de anuncios más grandes que eso. Entonces, todo lo que quieras hacer con respecto a la actividad de una conexión durante un mes será bastante rápido, creo. A través de las conexiones, obviamente cuanto más agarras, más costoso será (700MB para todas las 2000 conexiones). 700 MB es un número real que tiene un impacto real. Además, su proceso tendrá que ser agresivo al descartar los datos que no le interesan para que pueda descartar la paja (a menos que desee cargar hasta 700 MB de capacidad en el proceso de informe).

Dado estos números, Conexión/Día puede ser una mejor opción, ya que puede controlar la granularidad un poco mejor. Sin embargo, francamente, iría por el documento más burdo que pueda, porque creo que eso le da el mejor valor de la base de datos, únicamente porque hoy en día todas las búsquedas de cabeceras y las rotaciones de platos son lo que mata un montón de rendimiento de E/S, muchos discos transmitir datos muy bien. Documentos más grandes (suponiendo que los datos estén bien ubicados, ya que Couch se compacta constantemente, esto no debería ser un problema) transmitir más de lo que se busca. Buscar en la memoria es "gratuito" en comparación con un disco.

Por supuesto, ejecute sus propias pruebas en nuestro hardware, pero tenga en cuenta todas estas consideraciones.

EDIT:

Después de más experimentos ...

Un par de observaciones interesantes.

Durante la importación de documentos grandes, la CPU es igualmente importante para la velocidad de E/S. Esto se debe a la cantidad de marshalling y CPU consumida al convertir el JSON en el modelo interno para que lo utilicen las vistas. Al usar los documentos grandes (350k), mis CPUs estaban prácticamente agotadas (350%). Por el contrario, con los documentos más pequeños, estaban tarareando al 200%, aunque, en general, era la misma información, simplemente fragmentada de manera diferente.

Para E/S, durante los 350K documentos, estaba graficando 11MB/seg, pero con los documentos más pequeños, era solo 8MB/seg.

La compactación parecía estar casi unida a E/S. Es difícil para mí obtener buenos números en mi potencial de E/S. Una copia de un archivo en caché empuja 40 + MB/seg. La compactación se desarrolló a aproximadamente 8 MB/s. Pero eso es consistente con la carga bruta (asumiendo que el sofá está moviendo un mensaje de material por mensaje). La CPU es más baja, ya que está procesando menos (no está interpretando las cargas JSON o reconstruyendo las vistas), además de que era una sola CPU que hacía el trabajo.

Finalmente, para leer, traté de volcar toda la base de datos. Una sola CPU fue vinculada para esto, y mi E/S bastante baja. Me aseguré de que el archivo CouchDB no estuviera realmente en la memoria caché, mi máquina tiene mucha memoria, por lo que muchas cosas se almacenan en caché. El volcado sin procesar a través de _all_docs fue solo de aproximadamente 1 MB/seg. Eso es casi todo el retraso de búsqueda y rotación que cualquier otra cosa. Cuando lo hice con los documentos grandes, la E/S estaba llegando a 3 MB/seg, eso solo muestra el efecto de transmisión. Mencioné un beneficio para documentos más grandes.

Y debe tenerse en cuenta que existen técnicas en el sitio web de Couch para mejorar el rendimiento que no estaba siguiendo. Notablemente, estaba usando identificadores aleatorios. Finalmente, esto no se hizo como un indicador de cuál es el rendimiento de Couch, sino de dónde parece que termina la carga. Las diferencias entre documentos grandes y pequeños que pensé que eran interesantes.

Finalmente, el rendimiento máximo no es tan importante como el rendimiento suficiente para su aplicación con su hardware. Como mencionaste, estás haciendo tus propias pruebas, y eso es todo lo que realmente importa.

+0

CouchDB lanzará múltiples procesos del sistema para que el servidor de vistas procese una vista, por lo que escala bien en varios núcleos. El resto de CouchDB está en Erlang y también es excelente para usar múltiples núcleos. – mikeal

+0

Tienes razón. Ejecuté una prueba e inserté 2000 de estos documentos grandes (20 procesos que insertan 100 cada uno simultáneamente) en una instancia de Couch v0.9. En un Mac Pro 4,66G Mac, estos se insertaron en básicamente 3m30s. Couch tomó el 350% de la CPU. Al final, el archivo del disco era ~ 2G. Incluso después de la compactación, apenas cambió en absoluto. Por el contrario, insertar 2000 documentos de "un día" tomó ~ 18s. Mucho más rápido, por supuesto. 3m30s está demasiado cerca de la ventana de 5m que tienen. 18 años es mucho mejor. Sin embargo, la compactación tardó casi 3 millones. –

+0

Muchas gracias por esto, es un excelente lugar para comenzar. Hemos ejecutado algunos puntos de referencia y encontramos casi lo mismo que usted. El principal problema que vamos a tener es la constante actualización de los datos: parece que será demasiado lento para los documentos de "todo el mes". Siempre que podamos compactar regularmente, con suerte estaremos bien. Es una pena que no podamos obtener un documento por punto de datos, pero como sospechaba, el archivo IO parece prohibitivo. Lamentablemente para actualizar cualquier otro tipo de documento, tenemos que leer antes de que podamos escribir, con el fin de obtener el _rev ... – majelbstoat

Cuestiones relacionadas