2012-10-05 54 views
10

Acabo de entrar en las bases de datos de gráficos, y parece que me encuentro con un problema al decidir entre usar un "nodo de índice" o una "propiedad indexada" para rastrear cosas como "tipo de nodo". Como no tengo experiencia real hasta ahora, no tengo información para basarme en la decisión y ambos enfoques parecen ser igualmente válidos.¿Por qué los nodos de índice o una propiedad indexada serían mejores en una base de datos de gráfico?

Entonces, la pregunta es: ¿Cuáles son las ventajas y desventajas entre dos enfoques, y cómo la escala (es decir, el número de nodos) afecta la decisión?

Para un escenario de ejemplo, supongamos que hay dos tipos de "cosas": User y Product, y los bordes entre los nodos de usuario y los nodos de producto no importan tanto, pero lo que nos interesa es si queremos las propiedades type: User y type: Product en cada nodo, o si queremos que cada nodo tenga un borde apuntando hacia atrás en un nodo User y un nodo Product, respectivamente.

¿Qué enfoque es mejor bajo qué circunstancias?

Nota: Estoy viendo a Neo4j y a Titan en particular, pero creo que esto tenderá a aplicarse en términos más generales también.

Respuesta

18

en primer lugar, hay que preguntarse: ¿el tipo de un vértice/nodo necesidad de ser indexados? Es decir ¿necesita recuperar vértices/nodos por su tipo, digamos, recuperar todos los vértices de 'usuario' del gráfico o necesita responder consultas que comienzan recuperando todos los vértices de un tipo dado y luego filtrar/procesarlos más?

Si la respuesta a esta pregunta es , le sugiero que almacene el tipo como una propiedad de cadena que está indexada. O bien, si está desarrollando en un lenguaje basado en jvm, puede definir un tipo de enumeración y usarlo como el tipo de propiedad para más seguridad de tipo y comprobación automática de errores. Titan admite clases/enumeraciones arbitrarias definidas por el usuario como tipos de propiedad y las comprimirá para una huella de memoria baja.

Sin embargo, la desventaja de este enfoque es que no se escalará porque está creando un índice de baja selectividad. Lo que eso significa es que es probable que haya muchos vértices de tipo 'usuario' o 'producto' y todos ellos deben estar asociados con la entrada de índice para 'usuario' o 'producto' respectivamente. Esto hace que mantener y consultar este índice sea muy costoso y difícil de escalar (imagine que Facebook tenía un índice de 'tipo': la entrada de 'foto' tendría miles de millones de vértices). Si todavía no te preocupa el escalado, entonces esto puede funcionar.

Si la respuesta a la pregunta es no, entonces sugiero modelar tipos como vértices/nodos en el gráfico. Es decir. tiene un vértice de "usuario" y un vértice de "producto" y un borde etiquetado como "tipo" de cada usuario al vértice de "usuario", etc.

La ventaja de este enfoque es que utiliza el gráfico para modelar sus datos en lugar de tener valores de cadena fuera de su base de datos representan información de tipo crucial. A medida que crea su aplicación, la base de datos de gráficos se convertirá en su componente central y durará mucho tiempo. A medida que los lenguajes de programación y los desarrolladores van y vienen, no quiere que el modelado de datos y el tipo de información vayan con ellos y se enfrente a la pregunta: "¿Qué significa SPECIAL_USER?" Más bien, tenga un vértice SPECIAL_USER y añádale información de procedencia, es decir, quién creó este tipo, qué representa y una breve descripción: todo en la base de datos.

Un problema con este enfoque es que los vértices de 'usuario' y 'producto' tendrán muchos bordes incidentes en ellos a medida que la aplicación escala. En otras palabras, está creando supernodos que crean problemas de escala. Es por eso que Titan introdujo el concepto de un borde unidireccional. Un borde unidireccional es como un enlace en la web: el vértice inicial apunta a otro vértice, pero ese vértice ignora el borde. Como no desea atravesar el vértice del "usuario" para todos los vértices de usuario, no está perdiendo nada, sino que aumenta la escalabilidad y el rendimiento.

+0

Así que, en resumen, usar una propiedad indexada permite trabajar con todos los nodos de forma más sencilla a expensas de la escalabilidad, mientras que usar nodos índice es una representación más natural (es decir, estructural) a expensas de la escalabilidad . ¿De una forma u otra, se limita sustancialmente la forma en que se puede usar el gráfico? – cdeszaq

+0

No estoy seguro de que te esté siguiendo. En caso de que uno siga su recomendación para usar la segunda solución (por lo tanto, el uso de un borde para especificar el tipo), ¿cómo encuentra la lista de usuarios? ya que no puede atravesar desde el vértice del usuario hasta la lista de usuarios ... –

+0

Gracias por la excelente respuesta Mathias. ¿Pero podría hablar un poco más sobre/not/using edges unidirectional to the 'user' node? ¿Cuáles serían las implicaciones de eso en términos de consultas en cada dirección? (Supongo que no, y gran impacto, a menos que agregue propiedades de índice al borde).Y también con bordes unidireccionales, con Cassandra, te estás limitando a <10 millones de nodos de tipo "usuario", por ejemplo. –

4

¿Qué tipo de consulta desea realizar? En Neo4j, se crearía un índice User y una Product o incluso combinarlos en uno, y luego ser capaz de hacer cosas como

start bob = node:User(name='Bob') match .... 

e incluso realizar búsquedas textuales. Para verificar fácilmente si un nodo es un Usuario o Producto, podría tener la propiedad aún en los nodos, solo para un cruce conveniente y rápido. Si no está atravesando desde Usuario/Producto hasta los nodos de instancia (realiza las búsquedas de índice para eso), incluso puede hacer el control teniendo una relación PRODUCT o USER con los nodos de tipo (super), que le dan un check-in -traversal como

start s = node:User(name='Bob') match s-[r]-(product)-[typeRel:PRODUCT]->() return product 

HTH

0

Aquí se ha perdido una razón muy importante para la indexación. Supongamos que tiene un gráfico complejo con muchas propiedades diferentes, y muchos tipos de nodos diferentes, y desea hacer coincidir un patrón con una "persona" que tiene un montón de propiedades.

Sin índices, no tiene más opción que recorrer el gráfico, un gráfico en el que tal vez solo el 0,01% de los nodos son de tipo persona. Y los cruces pueden no llegar a las regiones no conectadas del gráfico.

En cambio, si tengo una persona indexada, simplemente repito a través de cada persona, y busco localmente alrededor de cada persona para ver si su patrón coincide.

Debería poder ver al instante que el primero de estos enfoques escala con el tamaño total del gráfico, pero el segundo solo escala con el número total de personas en el gráfico.

Moral: si prevé un caso de uso donde habrá muchas búsquedas del gráfico con un tipo particular de nodo como nodo vinculado en su patrón (por ejemplo, aquí muchas búsquedas de "personas con patrón X"), entonces debe indexar estos nodos para un mejor rendimiento de búsqueda.

Si va a buscar cosas como "todos los nodos dentro de los dos enlaces de la persona Peter", indexar a la persona por su nombre sería crítico y permitiría un rendimiento de tiempo constante independientemente del tamaño del gráfico, ya que esencialmente está buscando la ubicación de Peter en una tabla hash.

+0

La pregunta se centra en propiedades discretas, como 'nodeType', en lugar de propiedades de forma libre, como' personName', por lo que su punto acerca de encontrar el nodo de Peter no tiene en cuenta esta pregunta. Pero es una buena distinción, ya que la única forma sensata de indexar una propiedad freeform es con un índice tradicional. – cdeszaq

+0

Además, la pregunta es exactamente sobre cómo manejar el .01% de sus nodos. La pregunta es "en qué punto tienen más/menos sentido los nodos índice que un índice tradicional para campos discretos, como nodeType". La pregunta no es sobre el _razón_ para la indexación, se trata de _qué método de indexación funciona mejor, cuándo y por qué? _ – cdeszaq

Cuestiones relacionadas