2016-08-14 5 views
1

Я использую Neo4j для представления нашего хранилища данных. У нас есть ~ 100 000 узлов разных типов (~ 10), некоторые из которых имеют несколько ярлыков. Подмножество типичных типов узлов являются:Оптимальная стратегия индекса Neo4j для многоточечных узлов

(:User) 
(:Tableau:Workbook) 
(:Tableau:Dashboard) 

Здесь Tableau представляет собой программное обеспечение для визуализации данных и Workbook и Dashboard различные объекты Tableau. Причина, по которой мы отправились с несколькими ярлыками, а не с одной однозначно определенной меткой, - это то, что можно совместить все узлы (:Tableau) или все узлы (:Dashboard) (у нас есть несколько источников панели мониторинга).

Я также использую библиотеку UUID GraphAware Neo4j (https://github.com/graphaware/neo4j-uuid), чтобы гарантировать, что каждый узел (независимо от типа) однозначно идентифицируется с помощью свойства узла uuid.

Я создал индекс (и ограничение уникальности) для каждой этикетки узел для повышения производительности, т.е.

CREATE INDEX ON:User(uuid) 
CREATE INDEX ON:Tableau(uuid) 
CREATE INDEX ON:Workbook(uuid) 
CREATE INDEX ON:Dashboard(uuid) 

, учитывая, что CREATE INDEX должны точно один ярлык.

У меня возникли проблемы с производительностью при сопоставлении узлов с использованием Cypher с учетом этой структуры индексирования. Даже при том, что мощность (:Tableau:Dashboard) < < (:Tableau) следующего запроса является неоптимальной

MATCH (n:Tableau:Dashboard) WHERE n.uuid = <UUID> 

по сравнению с любым

MATCH (n:Tableau) WHERE n.uuid = <UUID> 
MATCH (n:Dashboard) WHERE n.uuid = <UUID> 

, учитывая, что первый не использовать какой-либо индекс, хотя поздние дела. Эта проблема усугубляется, если вы хотите найти узел глобально, основанный исключительно на уникальном UUID (который уникален), что часто бывает, когда мы используем API-интерфейс Flask для поиска узлов, что переводит на следующую логику Cypher:

MATCH(n) WHERE n.uuid = <UUID> 

следующий поток предполагает создание Entity всеобъемлющей глобальной метки узла и создания индекса на том, что (Neo4j: Create index for nodes with same property),

CREATE INDEX ON:Entity(uuid) 

так что теперь узлы с быть помечены следующим образом,

(:Entity:User) 
(:Entity:Tableau:Workbook) 
(:Entity:Tableau:Dashboard) 

Это лучший подход? Другим решением было бы просто выбрать первый ярлык, если будут определены несколько меток, учитывая, что он будет проиндексирован, однако он не решает проблему поиска узла исключительно на основе UUID.

Если я согласен с подходом лейбла Entity, все же имеет смысл сохранить все ранее определенные индексы, т. Е. Я ожидаю значительных улучшений производительности, если я ищу только небольшое подмножество узлов? Например, если бы я знал, что n был (:User) узел я должен ожидать, что подобные выступления с,

MATCH (n:Entity) WHERE n.uuid = <UUID> 
MATCH (n:User) WHERE n.uuid = <UUID> 

Не имея возможности индексировать ни на одном или нескольких индексов является позором, учитывая, что оптимальные Cypher запросы могут быть более абстрактным , т.е.скажем, что (:Tableau:Workbook) заполняющую (:Tableau:Dashboard) затем найти приборные панели, что книга населяет один будет запрашивать,

MATCH (s:Tabeau:Workbook)-[:POPULATES]->(t:Tableau:Dashboard) 
WHERE s.uuid = <UUID> 
RETURN t 

который является довольно прозрачным, однако следующий будет более оптимальным с точки зрения производительности, хотя и менее прозрачным, учитывая, что это не очевидно для пользователя, какой тип узла s является,

MATCH (s:Entity)-[:POPULATES]->(t:Tableau:Dashboard) 
WHERE s.uuid = <UUID> 
RETURN t 

ответ

0

Вы поддерживаете перекрывающихся индексы для Tableau и Workbook и Tableau и Dashboard. Почему бы просто не поддерживать индекс для Tableau, чтобы устранить избыточность и бросить планировщик запросов с помощью USING INDEX, чтобы убедиться, что он используется в вашем матче. т.е. что-то вроде этого ...

MATCH (s:Tableau:Workbook)-[:POPULATES]->(t:Tableau:Dashboard) 
USING INDEX s:Tableau(uuid) 
WHERE s.uuid = <UUID> 
RETURN t 
+0

Спасибо. Я не знал, что можно обеспечить использование индекса. Я понимаю, что у меня есть перекрывающиеся индексы, но это плохо? Таким образом, я всегда могу использовать индекс при сопоставлении любого типа узла, т. Е. 'MATCH (n: Dashboard) ИСПОЛЬЗОВАНИЕ INDEX n: Dashboard (uuid)', за исключением случаев, когда я не уверен в типе. – John

+0

np. Конечно, учитывая небольшой размер вашей базы данных, поддерживающий перекрывающиеся индексы, не будет проблемой. Если у вас есть бизнес-кейс для него, и он перевешивает дополнительные накладные расходы на поддержание индекса по определенному атрибуту дважды, то я говорю, иди за ним. –

Смежные вопросы