2015-08-03 4 views
3

Мне любопытно, как фильтры работают в запросах neo4j. Они приводят к хитам db (согласно PROFILE), и кажется, что они не должны.Профилирование запроса neo4j: фильтр для db-хитов

Пример запроса:

PROFILE MATCH (a:act)<-[r:relationship]-(n) 
WHERE a.chapter='13' and a.year='2009' 
RETURN r, n 
  1. NodeIndexSeek: (я создал индекс на этикетке act для chapter собственности) возвращает 6 строк.
  2. Фильтр: a.year == {AUTOSTRING1}, который приводит к ударам 12 дБ.

Почему это нужно делать какие-либо БД хитов, если он уже принес 6 совпадающие экземпляры a в ранее дб читает, она не должна просто фильтровать их вниз, не возвращаясь, чтобы сделать больше дб читает?

Я понимаю, что я приравниваю «db hits» к «db reads» здесь, что может быть неточным. Если нет, что такое «дБ-хиты»?

И наконец, число БД обращений, понесенных с помощью фильтра появляется примерно матч:

<number of filtering elements> * 2 * <number of already queried nodes to filter on> 

, где «число фильтрующих элементов» является количество фильтров при условии, т.е.

WHERE a.year='2009' and a.property_x='thing' 

является два элемента.

Спасибо за любую помощь.

EDIT: Вот результаты PROFILE и EXPLAIN по запросу. Это всего лишь пример запроса. Я нашел поведение

filter db hits = <number of filtering elements> * 2 * <number of already queried nodes to filter on> 

в целом верно в запросах, которые я выполнил.

Соответствие профиля (а: акт) < - [г: CHILD_OF] - (п) ГДЕ a.chapter = '13' И a.year = '2009' ВОЗВРАТ г, п

8 rows 
55 ms 

Compiler CYPHER 2.2 

Planner COST 

Projection 
    | 
    +Expand(All) 
    | 
    +Filter 
     | 
     +NodeIndexSeek 

+---------------+---------------+------+--------+-------------+---------------------------+ 
|  Operator | EstimatedRows | Rows | DbHits | Identifiers |      Other | 
+---------------+---------------+------+--------+-------------+---------------------------+ 
| Projection |    1 | 8 |  0 |  a, n, r |      r; n | 
| Expand(All) |    1 | 8 |  9 |  a, n, r |  (a)<-[r:CHILD_OF]-(n) | 
|  Filter |    0 | 1 |  12 |   a | a.year == { AUTOSTRING1} | 
| NodeIndexSeek |    1 | 6 |  7 |   a |    :act(chapter) | 
+---------------+---------------+------+--------+-------------+---------------------------+ 

Total database accesses: 28 

РАЗЪЯСНЯЕМ MATCH (а: акт) < - [г: CHILD_OF] - (п) ГДЕ a.chapter = '13' И a.year = '2009' ВОЗВРАТ г, п

4 ms 

Compiler CYPHER 2.2 

Planner COST 

Projection 
    | 
    +Expand(All) 
    | 
    +Filter 
     | 
     +NodeIndexSeek 

+---------------+---------------+-------------+---------------------------+ 
|  Operator | EstimatedRows | Identifiers |      Other | 
+---------------+---------------+-------------+---------------------------+ 
| Projection |    1 |  a, n, r |      r; n | 
| Expand(All) |    1 |  a, n, r |  (a)<-[r:CHILD_OF]-(n) | 
|  Filter |    0 |   a | a.year == { AUTOSTRING1} | 
| NodeIndexSeek |    1 |   a |    :act(chapter) | 
+---------------+---------------+-------------+---------------------------+ 

Total database accesses: ? 

ответ

1

Поскольку чтение узла (записи) и свойства чтения (записей) - это не то же самое действие db.

Вы правы, что фильтр попал не более 6. Обычно Neo4j извлекает фильтры и предикаты в самый ранний возможный момент, поэтому фильтр следует фильтровать непосредственно после поиска индекса.

В некоторых ситуациях, хотя (из-за предиката), он может фильтровать только после нахождения путей, тогда количество удалений db может равняться количеству проверенных путей.

Какой тип версии Neo4j вы используете? Можете ли вы поделиться своим полным планом запроса?

+0

По плану запроса Я предполагаю, что вы имеете в виду ПРОФИЛЬ И ОБЪЯСНЕНИЕ? Я добавил их на свой пост. Спасибо за вашу помощь. – RedCraig

+0

> Вы правы, что фильтр попал не более 6.
Похоже, что для каждого свойства узла, используемого в фильтре, читается БД, поэтому в моем примере выше он читает каждый узел раз в год сравнение и один раз для сравнения глав. Если бы у меня не было указателя на главу, это ожидаемое поведение? – RedCraig