Статьи

Разрешение разрешения с Neo4j — Часть 2

-принцесса-невеста original3

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

Файл node.csv (на самом деле разделенный табуляцией, c находится только для того, чтобы убедиться, что вы обратили внимание) выглядит следующим образом:

unique_id       type
9a984170-71cc-0130-92a0-20c9d042eca9    user   
9a984450-71cc-0130-92a0-20c9d042eca9    user   
9a984550-71cc-0130-92a0-20c9d042eca9    user
...
a67769a0-71cc-0130-92a0-20c9d042eca9    doc    
a6776a40-71cc-0130-92a0-20c9d042eca9    doc

Идентификаторы узла не установлены выше, вместо этого номер строки представляет идентификатор узла, который будет создан на нашем графике. Unique_id и тип являются свойствами узлов. Файл rels.csv также необходим, и он выглядит следующим образом:

start   end     type    flags
1       3003    IS_MEMBER_OF           
1       3060    IS_MEMBER_OF           
2       3032    IS_MEMBER_OF   
...
754949  272265  IS_CHILD_OF            
825621  283395  IS_CHILD_OF

В этом случае начальный и конечный столбцы — это идентификаторы узлов, которые связывают эти отношения через тип (обязательно) и некоторые свойства (если есть). Для создания этих файлов я создаю быстрый Rakefile, чтобы помочь мне сделать два набора из них. Один график будет иметь миллион узлов, остальные 10 миллионов, и мы увидим, насколько хорошо Neo4j масштабируется в этом отношении. Приведет ли увеличение в 10 раз количества документов на графике к увеличению производительности нашего алгоритма в 1/10 раз?

require 'neography/tasks'
require './neo_generate.rb'
 
namespace :neo4j do
  task :create do
    %x[rm *.csv]
    create_graph
  end
 
  task :create_bigger do
    %x[rm *.csv]
    create_bigger_graph
  end
   
  task :load do
    %x[rm -rf neo4j/data/graph.db]
    load_graph
  end
end

Методы создания и создания больших графов практически идентичны, единственная реальная разница в том, сколько узлов они будут создавать:

def create_graph
  create_node_properties
  create_nodes
  create_nodes_index
  create_relationship_properties
  create_relationships
end 
	
def create_bigger_graph
  create_node_properties
  create_more_nodes
  create_nodes_index
  create_relationship_properties
  create_relationships
end 

Мы собираемся установить первые 3000 узлов для пользователей, следующие 100 для групп, а следующие 1 миллион для документов.

def create_nodes   
 @nodes = {
           "user"  => { "start" =>     1, "end"   =>   3000},
           "group" => { "start" =>  3001, "end"   =>   3100},
           "doc"   => { "start" =>  3101, "end"   =>1003100}
          }
   
  @nodes.each{ |node| generate_nodes(node[0], node[1])}
end
rake neo4j:create

Файлы CSV, созданные для графа узла 1 миллион, не очень велики:

-rw-r--r--   1 maxdemarzi  staff    47M Mar 18 02:37 documents_index.csv
-rw-r--r--   1 maxdemarzi  staff    40M Mar 18 02:37 nodes.csv
-rw-r--r--   1 maxdemarzi  staff   259M Mar 18 02:46 rels.csv
-rw-r--r--   1 maxdemarzi  staff   140K Mar 18 02:37 users_index.csv

Теперь давайте загрузим их в:

rake neo4j:load
java -server -Xmx4G -jar ./batch-import-jar-with-dependencies.jar neo4j/data/graph.db nodes.csv rels.csv node_index Users exact users_index.csv node_index Documents exact documents_index.csv

Это запустит следующее:

Using Existing Configuration File
..........
Importing 1003100 Nodes took 2 seconds
.................................................................................................... 19508 ms for 10000000
.........
Importing 10976303 Relationships took 21 seconds
 
Importing 3000 Done inserting into Users Index took 0 seconds
..........
Importing 1000000 Done inserting into Documents Index took 7 seconds
 
Total import time: 34 seconds

Неплохо для 1 миллиона узлов и 10 миллионов отношений:

rake neo4j:start

Как только мы запустим neo4j и посмотрим на веб-администратора, мы увидим наш график:

Загрузить небольшой график

Для нашего большего графика мы просто добавляем еще один ноль и создаем 10 миллионов документов.

def create_more_nodes   
   @nodes = {
             "user"  => { "start" =>     1, "end"   =>    3000},
             "group" => { "start" =>  3001, "end"   =>    3100},
             "doc"   => { "start" =>  3101, "end"   =>10003100}
            }
     
    @nodes.each{ |node| generate_nodes(node[0], node[1])}
  end

Мы запустим другую задачу rake, которая перезапишет меньшие файлы csv.

rake neo4j:create_bigger

CSV-файлы, созданные для графа 10-миллионного узла, чуть больше, чем для графа 1-миллионного узла:

-rw-r--r--  1 maxdemarzi  staff   476M Mar 19 00:33 documents_index.csv
-rw-r--r--  1 maxdemarzi  staff   401M Mar 19 00:31 nodes.csv
-rw-r--r--  1 maxdemarzi  staff   510M Mar 19 05:16 rels.csv
-rw-r--r--  1 maxdemarzi  staff   140K Mar 19 00:33 users_index.csv

Давайте остановим сервер neo4j и вместо этого загрузим большой граф:

rake neo4j:stop
rake neo4j:load
java -server -Xmx4G -jar ./batch-import-jar-with-dependencies.jar neo4j/data/graph.db nodes.csv rels.csv node_index Users exact users_index.csv node_index Documents exact documents_index.csv

Интересно, сколько времени это займет

Using Existing Configuration File
.................................................................................................... 14052 ms for 10000000
 
Importing 10003100 Nodes took 14 seconds
.................................................................................................... 19242 ms for 10000000
..................................................................................................
Importing 19812750 Relationships took 37 seconds
 
Importing 3000 Done inserting into Users Index took 0 seconds
.................................................................................................... 64223 ms for 10000000
 
Importing 10000000 Done inserting into Documents Index took 64 seconds
 
Total import time: 135 seconds 

Это тоже неплохо. Чуть более двух минут

rake neo4j:start

10М график

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