2012-03-26 19 views
5

Esto es más bien más una pregunta de Lucene, pero está en el contexto de una base de datos neo4j.Indexación Neo4j (con Lucene): ¿una buena forma de organizar los "tipos" de nodos?

Tengo una base de datos que está dividida en aproximadamente 50 tipos de nodos (por lo tanto, "colecciones" o "tablas" en otros tipos de dbs). Cada uno tiene un subconjunto de propiedades que deben indizarse, algunas comparten el mismo nombre y otras no.

Al buscar, siempre quiero encontrar nodos de un tipo específico, nunca en todos los nodos.

puedo ver tres formas de organizar esta:

  • un índice por tipo, propiedades del mapa de forma natural a los campos de índice: índice de 'foo', 'id'='1234'.

  • Un índice global único, cada campo se asigna a un nombre de propiedad, para distinguir el tipo incluirlo como parte del valor ('id'='foo:1234') o verificar los nodos una vez que se devuelven (espero que los duplicados sean muy raros)

  • Un solo índice, tipo es parte del nombre del campo: 'foo.id'='1234'.

Una vez creada, la base de datos es de sólo lectura.

¿Hay algún beneficio para uno de ellos, en términos de conveniencia, tamaño/eficiencia de caché o rendimiento?

Según tengo entendido, para la primera opción, neo4j creará un índice físico separado para cada tipo, que parece no ser óptimo. Para el tercero, termino con la mayoría de los documentos de lucene teniendo solo un pequeño subconjunto de los campos, no estoy seguro si eso afecta algo.

+0

Tener un índice separado para cada tipo parece ser más conveniente y también más rápido, ya que el tamaño total de su índice será más pequeño. Pero me puede estar perdiendo algo. – biziclop

+0

@biziclop: En realidad, me pareció el menos conveniente, ya que tendría que gestionar la apertura/cierre de los índices individuales. Tengo entendido que el tamaño general también será mayor (ver la respuesta de jpountz). – Dmitri

+0

@Dimitri Bueno, obviamente el tamaño total será mayor, la pregunta es: ¿las búsquedas de todos los tipos se distribuyen de manera uniforme a tiempo? ¿O se buscan algunos tipos con mucha más frecuencia que otros? De cualquier manera, lo que haría es implementar la solución que considero más conveniente y ver si funciona bien. Si lo hace, tienes tu ganador. – biziclop

Respuesta

1

Un solo índice será más pequeño que varios pequeños índices, porque algunos datos, como el diccionario, se compartirán. Sin embargo, dado que una búsqueda de diccionario de términos es una operación O (lg (n)), una búsqueda en un diccionario de términos más grandes podría ser un poco más lenta. (Si tiene 50 índices, esto solo requerirá 6 (2^6> = 50) más comparaciones, es probable que no note ninguna diferencia.)

Otra ventaja de un índice más pequeño es que el caché del sistema operativo es probable que las consultas se ejecuten más rápido.

En lugar de las opciones 2 y 3, lo haría índice dos campos diferentes id y type y búsqueda de (id: Identificación Y type: TIPO), pero no sé si es posible con Neo4j.

+0

Usar campos múltiples es posible, pero un poco menos natural (por eso lo dejé): puede pasar una consulta específica de la implementación cadena directamente al motor de índice.Preferiría usar la API más general 'index.get (field, value)'. – Dmitri

+0

Entonces elegiría la segunda opción, que es la más natural (id: TYPE + ID) – jpountz

1

spring-data-neo4j está utilizando el primer enfoque: crea un índice diferente para cada tipo. Así que supongo que es una buena opción para el escenario general. Pero en su caso particular podría ser subóptimo, como usted dice. Me gustaría ejecutar algunos puntos de referencia para medir el rendimiento.

Las otras dos, por cierto, parecen un poco artificiales. Posiblemente esté indexando información completamente no relacionada en el mismo índice, lo cual no suena bien.

+0

No estoy seguro de que vea el problema de indexar datos no relacionados: si esta fuera una base de datos relacional, por ejemplo, la mayoría de estas propiedades probablemente se indexarían en una sola tabla de 'valor de atributo'. – Dmitri

+0

sí, puede que tenga razón. Para una indexación de texto completo es extraño, pero como lo está usando como un índice que respalda la tienda neo4j, no suena tan mal. – Bozho

2

Me encontré con este problema recientemente cuando estaba construyendo un adaptador de conexión ActiveRecord para Neo4j sobre REST, para ser utilizado en un proyecto de Rails. Desde ActiveRecord y ActiveRelation, ambos tienen un acoplamiento ajustado con sintaxis SQL, se hizo difícil ajustar todo en NoSQL.Puede que no sea la mejor solución, pero aquí es cómo lo resolví:

  1. Creado un índice llamado model_index el cual indexa linfáticos de dos llaves, type y model
  2. búsqueda en el índice con type clave sucede actualmente con sólo un valor model . Esto se introdujo principalmente para lograr una funcionalidad SQL SHOW TABLES que me permita obtener una lista de todos los modelos presentes en el gráfico.
  3. Búsqueda de índice con model La clave se lleva a cabo con los valores correspondientes a los diferentes nombres de modelo en mi sistema. Esto es principalmente para lograr la funcionalidad DESC <TABLENAME>.
  4. Con cada creación de tabla como en CREATE TABLE, se crea un nodo con atributos de definición de tabla que se almacenan en propiedades de nodo.
  5. El nodo creado está indexado en model_index con type:model y model:<model-name>. Esto habilita el modelo recién creado en la lista de 'tablas' y también permite que uno llegue directamente al nodo modelo mediante una búsqueda de índice con la clave model.
  6. Para cada registro creado por model (escriba en su caso), se crea un borde saliente etiquetado instances dirigido desde el nodo modelo a este nuevo registro. v[123] :=> [instances] :=> v[245] donde v [123] representa el nodo modelo y v [245] representa un registro del tipo v [123].
  7. Ahora, si desea obtener todas las instancias de un tipo especificado, puede buscar model_index con model:<model-name> para llegar a un nodo modelo y luego buscar todos los nodos adyacentes sobre un borde saliente etiquetado instances. Las búsquedas filtradas se pueden lograr mediante la aplicación de filtros y otros recorridos complejos.

La solución anterior impide que el modelo_índice se obstruya, ya que contiene 2x y logra una búsqueda efectiva de registros mediante una búsqueda de índice y un recorrido de un nivel.

Aunque en su caso, los nodos de diferentes tipos no son adyacentes entre sí, incluso si usted quisiera hacerlo, puede determinar el tipo de cualquier nodo arbitrario simplemente buscando su nodo adyacente con un borde entrante etiquetado instances . Además, estoy considerando incorporar el patrón SpringDataGraph de almacenar una propiedad __type__ en cada nodo de instancia para evitar esta búsqueda de nodo adyacente.

Actualmente estoy traduciendo AREL a scripts de Gremlin para casi todo. Puede encontrar el código fuente de mi adaptador de AR en https://github.com/yournextleap/activerecord-neo4j-adapter

Espero que esto ayude, ¡Salud! :)

+0

Esto suena como mi opción "2b": indexe todo junto, y use el gráfico para filtrar por tipo (ya sea con una verificación de borde o, como usted sugiere, una propiedad de tipo). Creo que me inclino por la opción 3, de modo que la búsqueda filtrada se puede realizar por completo en el índice. – Dmitri

+0

Una desventaja de confiar demasiado en los índices es que cuando necesita exportar su gráfico, ya sea en un GraphML o GraphSON, ninguno de los cuales conserva índices, necesita regenerar los índices cuando importa su gráfico en otro lugar. La indexación de todo en el gráfico podría significar un gran tiempo de respuesta para exportar-> importar. Además, si hay un subgráfico que está desconectado del nodo raíz, perder los índices en ese caso puede significar la pérdida de datos y se queda sin una opción infalible para llegar al subgráfico. – rhetonik

+0

Por lo tanto, le aconsejo que tenga todos sus nodos transitables desde el nodo raíz, en caso de que importe el gráfico desde un GraphML/SON previamente exportado. – rhetonik

Cuestiones relacionadas