Заставить планировщика затрат начать с определенного поиска индекса - PullRequest
0 голосов
/ 01 декабря 2018

Мой запрос на шифрование

EXPLAIN MATCH (b:Block)<-[:INCLUDED_IN]-(tx:Transaction {pstype: 0})
WHERE 1540512000 <= b.time < 1540598400
RETURN count(tx);

создает следующий план выполнения

--------------------------------------------+
| Operator          | Estimated Rows | Identifiers     | Other                                                                                                                                                                                                                                                                 |
+-------------------+----------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| +ProduceResults   |             12 | count(tx)       |                                                                                                                                                                                                                                                                       |
| |                 +----------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| +EagerAggregation |             12 | count(tx)       |                                                                                                                                                                                                                                                                       |
| |                 +----------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| +Filter           |            136 | anon[16], b, tx | AndedPropertyInequalities(Variable(b),Property(Variable(b),PropertyKeyName(time)),GreaterThanOrEqual(Property(Variable(b),PropertyKeyName(time)),Parameter(  AUTOINT2,Integer)), LessThan(Property(Variable(b),PropertyKeyName(time)),Parameter(  AUTOINT1,Integer))) |
| |                 +----------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| +Expand(All)      |           9052 | anon[16], b, tx | (tx)-[anon[16]:INCLUDED_IN]->(b)                                                                                                                                                                                                                                      |
| |                 +----------------+-----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| +NodeIndexSeek    |           9052 | tx              | :Transaction(pstype)                                                                                                                                                                                                                                                  |
+-------------------+----------------+-----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

, который выполняется слишком медленно, поскольку первый NodeIndexSeekByRange возвращает десятки миллионов узлов вместо 9052. Использование NodeIndexSeekByRangeна b: Блок (время) будет производить около 600 узлов.

Я пытался принудительно запустить план выполнения с b: Блок (время), но вместо этого он по-прежнему использует NodeIndexSeek для tx: Transaction (pstype):

EXPLAIN MATCH (b:Block)<-[:INCLUDED_IN]-(tx:Transaction {pstype: 0})
USING INDEX b:Block(time)
WHERE 1540512000 <= b.time < 1540598400
RETURN count(tx);

производит

+-------------------------+----------------+-----------------+--------------------------------------------------------------+
| Operator                | Estimated Rows | Identifiers     | Other                                                        |
+-------------------------+----------------+-----------------+--------------------------------------------------------------+
| +ProduceResults         |             12 | count(tx)       |                                                              |
| |                       +----------------+-----------------+--------------------------------------------------------------+
| +EagerAggregation       |             12 | count(tx)       |                                                              |
| |                       +----------------+-----------------+--------------------------------------------------------------+
| +NodeHashJoin           |            136 | anon[16], b, tx | b                                                            |
| |\                      +----------------+-----------------+--------------------------------------------------------------+
| | +NodeIndexSeekByRange |          14703 | b               | :Block(time) >= {  AUTOINT2} AND :Block(time) < {  AUTOINT1} |
| |                       +----------------+-----------------+--------------------------------------------------------------+
| +Expand(All)            |           9052 | anon[16], b, tx | (tx)-[anon[16]:INCLUDED_IN]->(b)                             |
| |                       +----------------+-----------------+--------------------------------------------------------------+
| +NodeIndexSeek          |           9052 | tx              | :Transaction(pstype)                                         |
+-------------------------+----------------+-----------------+--------------------------------------------------------------+

Единственный способ заставить его работать быстро - использовать планировщик правил: (на несколько порядков быстрее)

CYPHER planner=rule MATCH (b:Block)
WHERE 1540512000 <= b.time < 1540598400
WITH b
MATCH (b)<-[:INCLUDED_IN]-(tx:Transaction {pstype: 0})
RETURN count(tx);

Есть ли способ заставить его работать при использовании планировщика затрат?

Оба: блок (время) и: транзакция (pstype) проиндексированы.

1 Ответ

0 голосов
/ 01 декабря 2018

Вы можете попробовать использовать подсказку соединения на tx вместе с подсказкой индекса, что должно гарантировать, что вы расширяетесь только в одном направлении:

EXPLAIN 
MATCH (b:Block)<-[:INCLUDED_IN]-(tx:Transaction {pstype: 0})
USING INDEX b:Block(time)
USING JOIN ON tx
WHERE 1540512000 <= b.time < 1540598400
RETURN count(tx);

В качестве альтернативы вы можете реструктурировать свойВыполните запрос, так что узел tx изначально не является частью шаблона, но применяется в предложении WHERE.Вам нужно будет разделить МАТЧ на 2, но я не думаю, что вам понадобятся какие-либо подсказки для планировщика:

EXPLAIN 
MATCH (tx:Transaction {pstype: 0})
MATCH (b:Block)<-[:INCLUDED_IN]-(x)
WHERE 1540512000 <= b.time < 1540598400
AND x = tx
RETURN count(tx);

РЕДАКТИРОВАТЬ

Хорошо, давайте попробуем другой подход:

EXPLAIN 
MATCH (b:Block)<-[:INCLUDED_IN]-(x)
WHERE 1540512000 <= b.time < 1540598400
AND x.pstype = 0 // AND 'Transaction' in labels(x)
RETURN count(tx);

Если мы уберем ярлык, он не сможет использовать индексированный поиск.Если есть и другие узлы, кроме: Узлы транзакций, которые имеют свойство pstype, вы можете попробовать раскомментировать строку, где мы используем альтернативный способ, чтобы увидеть, имеет ли узел эту метку (я не думаю, что это будет использовать поиск по индексу,но не совсем уверен).

Другой альтернативой (не уверен, сработает ли это) является использование понимания шаблона для получения списка результатов из шаблона (после того, как начальное совпадение найдено до b) и суммированиеРазмеры результатов:

EXPLAIN 
MATCH (b:Block)
WHERE 1540512000 <= b.time < 1540598400
RETURN sum(size([(b)<-[:INCLUDED_IN]-(x:Transaction) WHERE x.pstype = 0 | x])) as count
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...