Почему скрывать аспекты в Neo4j плохо? - PullRequest
2 голосов
/ 01 апреля 2019

Я пытаюсь понять лучшие практики для создания сущности neo4j с учетом лучших практик, упомянутых в следующей статье о сокрытии аспектов https://neo4j.com/blog/dark-side-neo4j-worst-practices/

На следующем рисунке показано, что производительность лучше, когда "свойство country »моделируется как отношение к узлу Person, а не как его, заключенное в сам узел

Акцент делается на повышение производительности, когда оно моделируется как отдельный объект для запроса, который получает людей, которыежить в определенной стране.

https://s3.amazonaws.com/dev.assets.neo4j.com/wp-content/uploads/20160223191647/neo4j-data-modeling-hide-concepts.png

Случай 1: поле "страна" находится в Person Entity, поэтому запрос проходит через оба узла, чтобы проверить, является ли поле страны одинаковым

Случай 2: «Страна» как отдельная организация.

Я не могу понять, как в случае 2 количество проверок меньше.Пожалуйста, помогите мне .Большое спасибо за ваше время

1 Ответ

2 голосов
/ 02 апреля 2019

Здесь происходит несколько вещей, которые должны повлиять на ваше решение о моделировании.

Во-первых, когда мы извлекаем значение поля из узла, мы нормализуем данные. Вместо того, чтобы одинаковые значения (например, «Великобритания») дублировались для всех: узлов лиц, которые живут в Великобритании, теперь у нас есть только один узел: Страна с кодом «Великобритании», и все узлы людей, которые там живут, имеют : Отношения LIVES_IN к узлу страны. Так что в этом аспекте мы избегаем дублирования строковых данных в базе данных.

Еще одна вещь, которую следует учитывать, заключается в том, что в Neo4j поиск и фильтрация свойств часто являются одними из более дорогих операций, поэтому часто вы можете оптимизировать их, настраивая запросы и моделируя, чтобы минимизировать поиск свойств и фильтрацию свойств.

В первом случае нам всегда нужно отфильтровать всех моих друзей, чтобы получить друзей из желаемой страны. Хотя это не будет проблемой для такого небольшого набора данных, друзья одного человека, когда дело доходит до более сложных запросов, вы можете выполнять хороший поиск и фильтрацию свойств, что может замедлить выполнение запроса.

Во втором случае планировщик может быть в состоянии оптимизировать, сопоставляя страну с поиском по индексу (on: Country (code)) в дополнение к поиску узла Стефана (и если планировщик не делает этого мы можем использовать подсказки планировщика, чтобы заставить его). Предварительно сопоставив узел страны в Великобритании, мы можем расширить шаблон для друзей и узла их страны, который будет выполнять операцию ExpandInto в узле Великобритании (или хеш-соединение узла, в зависимости от подхода планировщика). В любом случае операция фильтрации вообще не требует доступа к свойству, вместо этого она выполняет фильтрацию на основе нашего предварительно согласованного британского узла (который скрывает фильтры на основе идентификатора графа узла), что является эффективной операцией.

Вы можете использовать PROFILE или EXPLAIN, чтобы проверить, как планировщик выполнит запрос.

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

Извлекая страны в их собственные узлы, мы теперь можем использовать эти узлы в разных контекстах. В то время как в настоящее время у нас есть отношения: LIVED_IN между узлами: Person и: Country, теперь мы можем добавлять любые другие виды отношений к узлам Country и от них. Мы могли бы иметь такие данные на графике:

(:Person)-[:TRAVELED_TO]->(:Country)
(:Language)-[:COMMONLY_SPOKEN_IN]->(:Country)
(:State)-[:LOCATED_IN]->(:Country)

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

Например: «Я хочу знать, какие мои друзья живут или путешествовали в страну, где обычно говорят по-испански, и вернуть друга и страны, которые совпадают»

MATCH (me:Person {name:'InverseFalcon'})-[:FRIENDS_WITH]->(friend)-[:LIVES_IN | TRAVELED_TO]->(country:Country)<-[:COMMONLY_SPOKEN_IN]-(:Language {name:'Spanish'})
RETURN friend, collect(country.code) as countries

Путем рефакторинга нашей модели, подобной этой, мы избегаем грубого извлечения значений свойств и необходимости использовать их в последующих сопоставлениях (аналогично объединениям таблиц).

...