MongoDB y claves primarias compuestas


Estoy tratando de determinar la mejor manera de tratar con una clave primaria compuesta en una base de datos mongo. La clave principal para interactuar con los datos en este sistema se compone de 2 uuid. Se garantiza que la combinación de uuid es única, pero ninguno de los uuid individuales lo es.

Veo un par de maneras de manejar esto:

  1. Utilice un objeto para la clave primaria que se compone de 2 valores (como se sugiere aquí)

  2. Utilice un mongo autogenerado estándar id de objeto como clave principal, almacene mi clave en dos campos separados y luego cree un índice compuesto en esos dos campos

  3. Hacer de la clave primaria un hash de los 2 uuids

  4. Alguna otra solución impresionante de la que actualmente no soy consciente

¿Cuáles son las implicaciones de rendimiento de estos enfoques?

Para la opción 1, me preocupa el rendimiento de inserción debido a que no tiene claves secuenciales. Sé que esto puede matar los sistemas tradicionales de RDBMS y he visto indicios de que esto podría ser cierto en MongoDB también.

Para la opción 2, parece un poco extraño tener una clave primaria que nunca sería utilizada por el sistema. Además, parece que el rendimiento de la consulta podría no ser tan bueno como en la opción 1. En un RDBMS tradicional, un índice agrupado proporciona los mejores resultados de consulta. ¿Qué tan relevante es esto en MongoDB?

Para la opción 3, esto crearía un solo campo de id, pero de nuevo no sería secuencial al insertar. Hay otros pros/contras de este enfoque?

Para la opción 4, bueno... ¿qué es la opción 4?

También, hay alguna discusión sobre la posibilidad de usar CouchDB en lugar de MongoDB en algún momento en el futuro. Con CouchDB sugieren una solución diferente?

MÁS INFORMACIÓN: algunos antecedentes sobre el problema se pueden encontrar aquí

Author: Pablo Santa Cruz, 2014-04-19

4 answers

Usted debe ir con la opción 1.

La razón principal es que dices que estás preocupado por el rendimiento - usar el índice _id que siempre está ahí y ya es único te permitirá ahorrar tener que mantener un segundo índice único.

Para la opción 1, me preocupa el rendimiento de inserción hacer a tener claves no secuenciales. Sé que esto puede matar los sistemas tradicionales de RDBMS y he visto indicios de que esto podría ser cierto en MongoDB también.

Su otro las opciones no evitan este problema, simplemente lo cambian del índice _id al índice único secundario, pero ahora tiene dos índices, una vez que está equilibrado a la derecha y el otro que es de acceso aleatorio.

Solo hay una razón para cuestionar la opción 1 y es si planea acceder a los documentos solo por uno u otro valor UUID. Mientras siempre esté proporcionando ambos valores y (esta parte es muy importante) siempre los ordene de la misma manera en todas sus consultas, entonces el el índice _id servirá eficientemente a su propósito completo.

Como una explicación de por qué debe asegurarse de ordenar siempre los dos valores de UUID de la misma manera, cuando se comparan subdocumentos { a:1, b:2 } no es igual a { b:2, a:1 }, podría tener una colección donde dos documentos tuvieran esos valores para _id. Por lo tanto, si primero almacena _id con el campo a, siempre debe mantener ese orden en todos sus documentos y consultas.

La otra precaución es que index on _id:1 será utilizable para consultas:

db.collection.find({_id:{a:1,b:2}}) 

Pero no será utilizable para la consulta

db.collection.find({"_id.a":1, "_id.b":2})
 33
Author: Asya Kamsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-26 22:43:53

Tengo una opción 4 para ti:

Use el campo automático _id y agregue 2 índices de campo único para ambos uuid en lugar de un índice compuesto único.

  1. El índice _id sería secuencial (aunque eso es menos importante en MongoDB), fácilmente fragmentable, y puedes dejar que MongoDB lo maneje.
  2. Los 2 índices uuid te permiten realizar cualquier tipo de consulta que necesites (con el primero, con el segundo o con ambos en cualquier orden) y ocupan menos espacio que 1 compuesto Indice.
  3. En caso de que utilice ambos índices (y otros también) en la misma consulta MongoDB se se intersecarán (nuevo en v2.6) como si estuviera utilizando un índice compuesto.
 6
Author: i3arnon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-28 11:42:02

Yo iría por la opción 2 y hay por qué

  1. Tener dos campos separados en lugar del concatenado de ambos uuid como se sugiere en 1st, le dejará la flexibilidad para crear otras combinaciones de índices para soportar las futuras solicitudes de consulta o, si resulta, que la cardinalidad de una clave es mayor que otra.
  2. tener claves no secuenciales podría ayudarlo a evitar los puntos de acceso mientras se inserta en un entorno fragmentado, por lo que no es una mala opción. La fragmentación es la mejor manera, para mi opinión, de escalar insertos y actualizaciones en las colecciones, ya que el bloqueo de escritura es a nivel de base de datos (anterior a 2.6) o a nivel de colección (versión 2.6)
 4
Author: Boris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-02 07:44:04

Habría optado por la opción 2. Aún puede crear un índice que maneje ambos campos UUID, y el rendimiento debe ser el mismo que una clave primaria compuesta, excepto que será mucho más fácil trabajar con ella.

Además, en mi experiencia, nunca me he arrepentido de darle a algo una identificación única, incluso si no era estrictamente necesario. Quizás sea una opinión impopular.

 2
Author: UltimateBrent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-22 18:15:26