mongodb composite-primary-key primary-key-design

MongoDB y claves primarias compuestas



composite-primary-key primary-key-design (4)

Estoy tratando de determinar la mejor forma de lidiar con una clave primaria compuesta en un mongo db. La clave principal para interactuar con los datos en este sistema se compone de 2 uuids. La combinación de uuids está garantizada para ser única, pero ninguno de los uuids individuales es.

Veo un par de maneras de manejar esto:

  1. Use un objeto para la clave principal que se compone de 2 valores (como se sugiere here )

  2. Use una identificación de objeto mongo autogenerada de forma estándar como clave principal, almacene mi clave en dos campos separados y luego cree un índice compuesto en esos dos campos

  3. Convierta la clave principal en un hash de los 2 uid

  4. Alguna otra solución impresionante que actualmente desconozco

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

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

Para la opción 2, parece un poco extraño tener una clave principal que el sistema nunca usaría. Además, parece que el rendimiento de la consulta puede 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 identificación, pero nuevamente no sería secuencial al insertar. ¿Hay otros pros / contras en este enfoque?

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

Además, hay una discusión sobre la posibilidad de usar CouchDB en lugar de MongoDB en algún momento en el futuro. ¿El uso de CouchDB sugiere una solución diferente?

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


Deberías ir con la opción 1.

La razón principal es que dices que te preocupa el rendimiento: utilizar el índice _id, que siempre está presente y que ya es único, te permitirá ahorrar para tener que mantener un segundo índice único.

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

Sus otras opciones no evitan este problema, simplemente lo cambian del índice _id al índice único secundario, pero ahora tiene dos índices, una vez que está bien balanceada y la otra que tiene acceso aleatorio.

Solo hay una razón para cuestionar la opción 1 y eso es si planea acceder a los documentos con solo uno o solo el otro valor de UUID. Siempre que siempre proporcione ambos valores y (esta parte es muy importante) siempre los ordena de la misma manera en todas sus consultas, entonces el índice _id servirá de manera eficiente su propósito completo.

Como una explicación de por qué tiene que asegurarse de que siempre ordena los dos valores de UUID de la misma manera, al comparar los subdocumentos { a:1, b:2 } no es igual a { b:2, a:1 } - podría tener una colección donde dos documentos tenían esos valores para _id. Por lo tanto, si almacena _id con un campo primero, entonces siempre debe mantener ese orden en todos sus documentos y consultas.

La otra precaución es que el índice en _id:1 será utilizable para consulta:

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

pero no será utilizable para consulta

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


Me hubiera ido con la opción 2. Aún puedes crear un índice que maneje ambos campos UUID, y el rendimiento debería ser el mismo que el de una clave primaria compuesta, excepto que será mucho más fácil trabajar con él.

Además, en mi experiencia, nunca me arrepentí de haberle dado a alguien una identificación única, incluso si no era estrictamente necesario. Sin embargo, tal vez sea una opinión impopular.


Tengo una opción 4 para ti:

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

  1. El índice _id sería secuencial (aunque eso es menos importante en MongoDB ), fácilmente ampliable, y puedes dejar que MongoDB administre.
  2. Los 2 índices de uuid le permiten realizar cualquier tipo de consulta que necesite (con el primero, con el segundo o con ambos en cualquier orden) y ocupan menos espacio que un índice compuesto.
  3. En caso de que use ambos índices (y otros también) en la misma consulta, MongoDB los intersecará (nuevo en v2.6) como si estuviera usando un índice compuesto.

Yo iría por la opción 2 y ahí está el porqué

  1. Tener dos campos separados en lugar de uno concatenado de ambos uuids como se sugirió en 1er lugar, te dejará la flexibilidad de crear otras combinaciones de índices para respaldar las futuras solicitudes de consulta o si resulta que la cardinalidad de una clave es más alta que la de otra.
  2. tener claves no secuenciales podría ayudarte a evitar los puntos de acceso mientras se inserta en un entorno fragmentado, por lo que no es una opción tan mala. Sharding es la mejor manera, en mi opinión, de escalar insertos y actualizaciones en las colecciones, ya que el bloqueo de escritura está en el nivel de la base de datos (anterior a 2.6) o en el nivel de recopilación (versión 2.6)