Neo4j плохая производительность с оператором ИЛИ - PullRequest
1 голос
/ 28 мая 2019

Я использую версию сообщества neo4j-3.5. И построил огромный график, используя neo4j, содержащий ~ 20 миллионов узлов данных фильма. Я также вставил жанры и ключевые слова и построил график. Следующий запрос занимает> 5 секунд

MATCH 
    (p:`Program`),  
    (p:Program)-[genre:of_genre]->(g:Genre), 
    (p:Program)-[key_rel:associated_keyword]->(k:Keyword)
  WHERE   
    ((g.id IN [1010]) OR (k.id IN ['keyword_121'])) AND 
    ((p.show_type IN ['movie'])) AND 
    (p.imdb_score > 0)
  RETURN distinct p.id, p.imdb_score
  ORDER BY p.imdb_score desc
  LIMIT 50

, тогда как, если я заменяю ИЛИ на И, это займет <100 мс. </p>

MATCH 
    (p:`Program`),  
    (p:Program)-[genre:of_genre]->(g:Genre), 
    (p:Program)-[key_rel:associated_keyword]->(k:Keyword)
  WHERE   
    ((g.id IN [1010]) AND (k.id IN ['keyword_121'])) AND 
    ((p.show_type IN ['movie'])) AND 
    (p.imdb_score > 0)
  RETURN distinct p.id, p.imdb_score
  ORDER BY p.imdb_score desc
  LIMIT 50

Имеются индексы для идентификатора жанра и ключевого слова.

Ответ PROFILE для «ИЛИ»:

enter image description here

ПРОФИЛЬ ответ для 'И':

enter image description here

Есть ли лучший способ написать запрос с оператором OR?

Ответы [ 2 ]

0 голосов
/ 29 мая 2019

Этот может работать лучше для вас:

OPTIONAL MATCH (g:Genre) WHERE g.id IN [1010]
OPTIONAL MATCH (k:Keyword) WHERE k.id IN ['keyword_121']
WITH g, k
MATCH (p:`Program`)
WHERE
  p.show_type IN ['movie'] AND
  p.imdb_score > 0 AND
  ((p)-[:of_genre]->(g) OR (p)-[:associated_keyword]->(k))
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50

В этом запросе могут использоваться оба ваших индекса (или, по крайней мере, вы можете дать подсказки использовать их).Кроме того, вы можете создать индекс на :Program(show_type), если фильмы не очень распространены в вашей БД.

Предложение WHERE также просто проверяет наличие единственного желаемого :of_genre или * 1013.* отношения - он не пытается на самом деле сканировать и удерживать в памяти все из них.

0 голосов
/ 28 мая 2019

Ваш запрос строит декартово произведение из 3-х отключенных шаблонов.

Попробуйте следующий запрос:

  MATCH 
    (k:Keyword)<-[key_rel:associated_keyword]-(p:Program)-[genre:of_genre]->(g:Genre)
  WHERE   
    ((g.id IN [1010]) OR (k.id IN ['keyword_121'])) AND 
    ((p.show_type IN ['movie'])) AND (p.imdb_score > 0)
  RETURN distinct p.id, p.imdb_score
  ORDER BY p.imdb_score desc
  LIMIT 50
...