Sin categoría

Couchbase 103: Preguntas y respuestas

En nuestra serie de formación continua, cada vez surgen una serie de preguntas, que enumero a continuación con sus respectivas respuestas.

Couchbase 103 - Modelado de documentos

P: Suponiendo que se pueda almacenar un documento como XML en lugar de JSON, ¿qué opinas de uno frente al otro para Couchbase?

R: Puede almacenar XML, como nosotros podemos almacenar cadenas. Sin embargo, es difícil hacer Map-Reduce Views para indexarlos y consultarlos, ya que no analizamos XML del lado del servidor para poder utilizar la anotación por puntos como con JSON. XML no es nativo de javascript. La extensión E4X para parsear XML no es parte del motor V8 que usamos en Couchbase para procesar las funciones map de javascript.

P: ¿Podemos hacer inserciones/actualizaciones masivas en Couchbase?

R: Típicamente haces esto de la misma manera que haces cualquier operación CRUD con Couchbase, usas los SDK's. Tenemos una herramienta de línea de comandos que puede leer archivos JSON del disco, cbtransfer. Recomiendo usar una VM rápida (por ejemplo Java/C/C++/Go en vez de Ruby) y paralelizar el esfuerzo si es una gran cantidad de documentos.

P: ¿No se está volviendo al patrón "relacional" cuando se utiliza el patrón de documentos múltiples?

R: No necesariamente, es más una separación de preocupaciones, pero sigue sin haber uniones. Se trata simplemente de aislar los comportamientos de los usuarios en documentos separados, no de normalizarlos. Hay una gran diferencia entre los dos. En lugar de tener un documento para muchos comportamientos de usuario, se aíslan los documentos por clave para determinados comportamientos de usuario y se siguen almacenando datos desnormalizados. Lo que estamos consiguiendo al utilizar JSON en lugar de tablas y datos desnormalizados en lugar de normalizados es la capacidad de distribuir los datos. Cuando se tienen tablas normalizadas, la distribución de los datos y la computación de las uniones es muy difícil. No se pueden dividir fácilmente grandes tablas en múltiples servidores, y cuando se hace, la computación de las uniones requiere la agregación de grandes tablas en múltiples servidores, lo que va a ser pesado en términos de computación y transferencia de datos, e incapaz de sostener muchas consultas. Por supuesto, la lógica de las operaciones CRUD en una situación de RDBMS distribuido es igual de compleja.

P: Según su experiencia, ¿cuál es la mejor manera de garantizar en la medida de lo posible que un artículo se remita con el mismo nombre a través de la base de datos?

R: En primer lugar, elija características inmutables para las claves, de esa manera los id's referenciales dentro del documento JSON no necesitan ser actualizados. Si necesitas cambiar una clave que ha sido referenciada en otros documentos, probablemente tendrás que crear una Vista para encontrar y actualizar esos documentos después del cambio de clave.

P: Ha señalado que una de las ventajas de CB es la línea recta entre la aplicación y los datos almacenados en la base de datos, es decir, la ausencia de desajustes de impedancia. WQué pasa si la aplicación cambia y se utilizan datos diferentes en páginas diferentes, o (aún peor) cuando varias aplicaciones están consultando los mismos datos. ¿No es mejor entonces el enfoque RDBMS? o ¿seguirías defendiéndolo? En caso afirmativo, ¿por qué?

R: Si se utilizan diferentes partes de un documento JSON en diferentes páginas, no hay problema. Si diferentes comportamientos de usuario modifican el mismo documento y existe la posibilidad de que se produzcan condiciones de carrera, puede utilizar operaciones CAS o puede separar los documentos en varios. Si varias aplicaciones consultan los mismos datos, tampoco es un problema. Si estas aplicaciones son aplicaciones de terceros que pueden hacer escrituras en los datos, es mejor si van a través de una API para que el formato de las claves JSON y otras validaciones se pueden hacer para mantener el formato y la integridad de los datos. En los sistemas RDBMS dependes de la base de datos para hacer la validación de tipo, esta responsabilidad se mueve de la base de datos a la App Tier con Couchbase. Es bastante fácil de resolver, y es una mejor práctica de todos modos que las aplicaciones de terceros vayan a través de una API en lugar de directamente a la base de datos. Incluso en el caso de múltiples aplicaciones interactuando con la misma base de datos, usar SOA podría ser una mejor arquitectura también.

P: ¿Cómo se "encuentra" el tamaño (en términos de bytes en disco, por ejemplo) de un documento concreto?

R: No tenemos una manera de hacer esto para los documentos individuales. Los documentos se comprimen en disco, utilizando Snappy, por lo que puede tomar una relación de compresión media del tamaño del documento desde el lado del cliente (json sin comprimir) y luego tomar una compresión arbitraria de 40% para ver su huella en disco. O usted puede tomar un promedio mirando el número de elementos (documentos) y tomando el uso de disco y dividirlo para ver el tamaño promedio de doc en el disco.

P: ¿Cómo "actualizar" los elementos json, por ejemplo, la fecha y hora de actualización del documento, utilizando cualquier método que no sea manual?

R: No existe un mecanismo automático para actualizar claves json individuales dentro de un documento json. Documentos enteros son pasados de un lado a otro con operaciones CRUD. Si está actualizando cualquier clave json con un nuevo valor, se hace del lado del cliente, incluyendo y no limitado a la actualización de una marca de tiempo.

P: ¿Cómo se gestiona la actualización de datos? ¿No lleva mucho tiempo?

R: Si te refieres simplemente a actualizar el documento JSON, por supuesto que la operación de reemplazo en sub-milisegundos no es a lo que te refieres. Por lo tanto, tuve que hacer una suposición para responder a esta pregunta, que se refiere a la migración de una estructura de documento JSON a otra, como tener un documento de usuario que tiene algunas claves JSON y desea agregar/eliminar/transformarlas. Como mencioné en el webinar, puedes hacerlo de múltiples formas. Por supuesto, tiene dos formas diferentes, uno es un estilo de trabajo por lotes / cron, donde se itera a través de los documentos y hacer su transformación / mutación. El tiempo que esto lleva depende del tamaño de tu conjunto de datos, cuántas máquinas hay en tu cluster de Couchbase, y cuántas máquinas están haciendo las transformaciones. Así que "consume tiempo" es una valoración relativa. La otra forma de afrontarlo sería transformar los documentos "bajo demanda", es decir, cuando son recuperados por el uso normal de tu aplicación. Por ejemplo, cuando un usuario hace un login, puedes recuperar el documento del usuario, transformarlo, y reemplazarlo en Couchbase.

P: Lo que Jasdeep no ha mencionado es que los datos deben residir en memoria (al menos para justificar la velocidad). Entonces, ¿cuál es la ventaja con respecto a una base de datos relacional en memoria que admita SQL enriquecido? También hacen un buen clustering ...

R: Si se trata de un único nodo a escala vertical de una base de datos relacional en memoria, el límite será la escala vertical de esa única máquina. Una vez que tengas más de un servidor y uniones (y particularmente uniones distribuidas) encontrarás cuellos de botella en el rendimiento similares a los de los ancestros de disco, puramente debido a la física. Si haces una unión a través de una conexión de red en muchas tablas grandes, no importa cómo lo cortes, va a ser lento, y si las haces a menudo, todo el rendimiento se degradará a escala.

P: En un patrón Counter-ID para Usuarios, ¿dónde residirá el valor de recuento de usuarios?

R: Es un simple valor entero positivo con una clave, como "user::count". Asegúrate de que sólo incrementas tu contador. Y síguelo con una operación add en lugar de set, de esa manera si tienes un error lógico entonces lo detectarás.

P: ¿Cómo se hace un MapReduce de índice inverso (invertido)?

R: Esto es más sobre el tema del webinar Couchbase 104: Views. Pero los índices inversos son complicados con Map-Reduce, puedes crearlo emitiendo la etiqueta para cuando ocurra y luego consulta de rango para esa etiqueta.

P: ¿Cuándo se dividen los documentos en varios?

R: En general, hay tres razones para pensar en dividir un documento en varios documentos. La primera es que una determinada acción de usuario puede modificar un documento que también puede ser modificado por otra acción de usuario (y ambas son frecuentes). Si varios usuarios pueden modificar el mismo documento en un momento dado (o casi simultáneamente), se trata de una "condición de carrera" y deberías aislar ese documento y utilizar operaciones CAS. En segundo lugar, cuando un único documento puede estar "hinchado" o ser muy grande, en cuyo caso puede ser más eficiente tenerlo dividido en términos de código y mantenimiento del código. En tercer lugar, si se utiliza un contador atómico para representar un componente concreto de un objeto/clase. Esto tendrá que ser su propio par clave-valor independiente del documento JSON primario, por supuesto.

P: ¿Cómo se realiza una búsqueda si se dispone de un ID de buque y una Lat/Long y se desea buscar por cualquiera de los dos parámetros?

R: En ese caso, como las coordenadas geográficas tienen una precisión de tres decimales, ningún patrón de teclas le ayudará. Sin embargo, tenemos dos opciones para hacer búsquedas del tipo de información que desea. Nuestras vistas generales Map/Reduce son más que satisfactorias, pero también tenemos vistas especializadas con Geo. Estos permiten la búsqueda en cajas delimitadas y otras técnicas Geo más avanzadas. No hablo de eso específicamente en el webinar Couchbase 104: Views, pero contáctame si estás interesado en aprender más o necesitas asistencia con respecto a Geo y Couchbase.

P: ¿Es contar los usuarios una mejor manera (con la función .incr()) de crear el userID que por ejemplo un gran número aleatorio o un GUID? Me refiero al caso en el que puede haber muchos usuarios nuevos por segundo, ¿el recuento no dará lugar a más conflictos que una gran clave aleatoria que tiene una probabilidad muy baja de conflicto?

R: Dado que los contadores atómicos son, bueno, atómicos, entonces puedes contar con ellos (en un único cluster), para ser ejecutados en orden. Si todos tus servidores de aplicaciones están apuntando a ese cluster, entonces todos están ejecutando operaciones incr simultáneamente. Pero como son atómicas, cada operación de cada servidor de aplicaciones que ejecute operaciones generará un nuevo entero, por lo que todas serán únicas. Si nunca usas una operación decr (decremento) entonces estás bien. Se vuelve un poco más complejo si tienes múltiples centros de datos y estás usando XDCR (Cross Data Center Replication). En esos casos es mejor prefijar sus contadores por id de centro de datos (que usted crea).

P: Estoy usando la gema couchbase-model en Rails, y me está costando hacerme con Counter-ID y namespacing de las claves en el paradigma Rails, por ejemplo, usando el método Object.find() o accediendo/incrementando refdocs no JSON. ¿Podrías publicar un ejemplo que combine Counter-ID con Rails, incluyendo el incremento desde el bucket del modelo?

R: Esto va a necesitar algo mejor que un blog para mostrarse. Encontraré la forma de hacer un resumen y publicar un enlace aquí. Dame un poco de tiempo para hacerlo :)

P: ¿Existe alguna forma de obtener varios documentos para diferentes identificadores? El ejemplo que estoy pensando es tener una lista de identificadores de usuario de Facebook que queremos asignar a sus documentos de usuario. ¿Hay alguna forma de pasar varios identificadores de Facebook y obtener una matriz de documentos?

R: Tenemos una operación multi-get en cada sdk sólo para este propósito. En el array resultante si el documento no existía, tendrá un elemento null/nill para indicarlo (quizás Java tenga un retorno diferente, tendré que comprobarlo, pero sé que también lo tiene).

P: ¿Son las vistas la única forma de utilizar las teclas compuestas? ¿Existe alguna forma de utilizar este tipo de funcionalidad sin una vista con teclas get o setup? https://www.couchbase.com/blog/understanding-grouplevel-view-queries-compound-keys 

R: Esto es más un tema para Couchbase 104: Views and Indexing, pero básicamente una clave puede ser lo que quieras, así que técnicamente, sí, puedes tener una clave compuesta (sólo depende de cómo definas compuesta). Sin embargo, el enlace al que te refieres se centra en la consulta de un View-Index, y esos también tienen claves, index-keys, con las que construimos nuestros B+trees. En ese caso, estás tomando partes de la clave y dividiéndola en base al delimitador "," (coma). Es una bestia diferente de la que estamos hablando.

P: Actualmente estamos utilizando una vista para buscar el ID de usuario de Facebook para obtener el ID de usuario de nuestra propia aplicación. Suena como si realmente usamos el patrón de búsqueda que sugirió que esto puede ser más rápido que el uso de una vista?

R: Sí, y por supuesto depende. La escala también es un factor. Cuantos más nodos haya en el clúster, más amplio será el proceso de dispersión y recopilación de consultas de visualización, es decir, más nodos tendrá que dispersar y recopilar en términos de resultados de consultas de visualización. Por lo tanto, sólo por física, Lookup será más rápido. La contrapartida es que estás añadiendo más documentos, y por lo tanto más requisitos de RAM/metadatos, pero estás ganando una tremenda escalabilidad como resultado, porque las operaciones binarias van a través de una conexión persistente a un servidor para el facebook_id->app_user_id, y luego de nuevo una segunda operación binaria al mismo o a otro nodo a través de una conexión persistente siempre será más rápida que dispersar una consulta View a través de todos los nodos y recopilar los resultados. Las vistas son muy potentes porque son más flexibles que los patrones clave, sin embargo en este escenario, apuesta por la velocidad.

P: Las vistas tienen una opción stale que parece que puede mitigar el problema de la constancia frente a dos llamadas get separadas. ¿Es realmente más rápido tener dos llamadas a la base de datos frente a una vista bien gestionada? Podría preocuparme a escala, dos llamadas frente a una en una vista.

R: No mitiga el problema de consistencia. Los índices son siempre eventualmente consistentes en Couchbase (hasta que lo evolucionemos nosotros mismos, lo cual está en el radar), pero por favor lee la pregunta/respuesta anterior así como mira Couchbase 104: ¡Vistas e Índices! Puede que cambie tu opinión.

P: En el ejemplo que está mostrando, estamos hablando de un único documento y sus atributos/propiedades a través de JSON. ¿Cómo manejamos, si desea obtener stat / recuento a través de múltiples objetos / documentos Por ejemplo: a) ¿me consigues todos los usuarios con color azul favorito? b) ¿me consigues todos los usuarios que usan tarjeta de crédito visa?

R: Esto requiere Views y la técnica Map/Reduce para reunir todos esos elementos de datos del documento y ponerlos en una estructura de Índice para que puedas hacer consultas como esas. Este es un buen ejemplo de cosas que realmente no puedes hacer con Key patterns, y requieren la integración de VIews y/o Elastic Search. En estos escenarios que comentas, podrías utilizar cualquiera de las dos soluciones.

P: *¿Requiere* views/map-reduce? ¿Qué pasa si se almacena el segundo documento u::uuid { email:user@domain.com } para luego acceder a u:user@domain.com? ¿Cuándo debe hacerse esto sobre view/map-reduce?

R: Esta pregunta se refería a lo que ocurre sin un patrón de búsqueda. Si tienes claves de documento generadas aleatoriamente, normalmente necesitas crear un índice para poder buscar documentos a través de diferentes propiedades JSON. Sin embargo, si creas un patrón de búsqueda, puedes hacer una doble búsqueda para obtener el documento primario, la primera búsqueda se basará en información conocida (dirección de correo electrónico), el valor será el identificador generado aleatoriamente que corresponde al documento primario; la segunda búsqueda utilizará ese valor y obtendrá el documento primario.

P: ¿Cuál es la mejor manera de consultar esos documentos de notificación?

R: En el ejemplo que mencionaba, las propias claves son marcas de tiempo que indican cuándo deben enviarse las notificaciones. Aquí hay un gist que puede ayudar a explicar el paradigma: https://gist.github.com/scalabl3/7235173

P: El objetivo principal de la normalización es evitar anomalías de actualización; dado que todos los programas tienen errores, ¿hay alguna forma en couchbase de evitar estas anomalías de actualización y no tener que depender de que el desarrollador "lo haga bien"?

R: El principal objetivo de la normalización era ahorrar espacio en disco. Si nos remontamos a la época en que se creó SQL, conseguir aproximadamente 1 GB de almacenamiento en disco (lo que no era posible en un solo disco) suponía alrededor de $700.000. La normalización redujo la redundancia de datos al apuntar a los mismos datos desde múltiples lugares, y luego volver a ensamblar esos datos agregándolos o JOIN'ing juntos. En la práctica, quedó claro muy pronto que si se insertan, actualizan y borran datos en un esquema normalizado, si falla alguna de las partes, la integridad de los datos se va al garete. Precisamente por la normalización son necesarias las transacciones. En una forma desnormalizada, o forma agregada, las transacciones se vuelven mucho menos necesarias, pero tenemos concurrencia optimista y concurrencia pesimista para tener transacciones de documento único y se puede utilizar una confirmación de dos fases.

En realidad, ningún sistema es a prueba de errores para los desarrolladores. Avísame si lo descubres :).

P: ¿No sería ventajoso combinar el patrón Counter-ID con el patrón Lookup?

R: Definitivamente es ventajoso porque entonces usted tiene un recuento total de documentos para ese tipo también. Si se utiliza un identificador aleatorio y una búsqueda, no se dispone del recuento total. Con el recuento total, puede iterar a través de la colección simplemente generando claves por lotes hasta el recuento total. De lo contrario, tendrá que crear una vista (un índice) para recorrer la colección.

P: ¿Acaso un índice para el RDBMS no ofrece también un rendimiento lineal?

R: Te ofrece un gran rendimiento siempre que puedas vivir en un solo servidor y escalarlo verticalmente. El lío viene cuando tienes que dividir el tráfico en más de un servidor. Aquí es donde el nacimiento de todas las nuevas bases de datos explotó en la escena podría remontarse a principios de la década de 2000, cuando el público "voló" la capacidad de las bases de datos relacionales para manejar grandes cantidades de tráfico. Cosas como memcached llegaron primero, y luego las NoSQL.

P: ¿Por qué no ampliar CB con funcionalidades abstractas basadas en esos patrones, en el lado del servidor? ahora mismo, los patrones deben implementarse individualmente en el lado del cliente.

R: Es una idea, y de hecho creo que tiene cierta validez hacerlo, pero también hay un buen argumento en el otro lado de que debería estar bajo control programático. En cuanto se añade una nueva función, la gente quiere jugar con ella :)

¡Gracias por asistir a Couchbase 103!

Jasdeep
@escalable

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Jennifer García

Jennifer Garcia es Gerente Senior de Web en Couchbase Inc. Como responsable del sitio web, Jennifer tiene la responsabilidad general de las propiedades del sitio web, incluido el diseño, la implementación, el contenido y el rendimiento.

1 Comentarios

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.