Архитектура
Данные хранит в собственном формате, специализированно приспособленном для представления графовой информации, такой подход в сравнении с моделированием графовой базы данных средствами реляционной СУБД позволяет применять дополнительную оптимизацию в случае данных с более сложной структурой. Также утверждается о наличии специальных оптимизаций для SSD-накопителей, при этом для обработки графа не требуется его помещение целиком в оперативную память вычислительного узла, таким образом, возможна обработка достаточно больших графов.
Компоненты графовой базы данных — узлы и ребра. Они могут быть дополнены собственным набором полей. Модель такой БД схематично изображена на рисунке.
Рис. 1. Модель БД
Терминология Neo4j и графовых баз данных в целом
- graph database, графовая база данных — база данных построенная на графах — узлах и связях между ними
- Cypher — язык для написания запросов к базе данных Neo4j (примерно, как SQL в MYSQL)
- node, нода — объект в базе данных, узел графа. Количество узлов ограниченно 2 в степени 35 ~ 34 биллиона
- node label, метка ноды — используется как условный «тип ноды». Например, ноды типа movie могут быть связанны с нодами типа actor. Метки нод — регистрозависимые, причем *Cypher не выдает ошибок, если набрать не в том регистре название.
- relation, связь — связь между двумя нодами, ребро графа. Количество связей ограниченно 2 в степени 35 ~ 34 биллиона
- relation identirfier, тип связи — в Neo4j у связей. Максимальное количество типов связей 32767
- properties, свойства ноды — набор данных, которые можно назначить ноде. Например, если нода — это товар, то в свойствах ноды можно хранить id товара из базы MySQL
- node ID, ID нода — уникальный идентификатор ноды. По умолчанию, при просмотрах результата отображается именно этот ID.
Сохранение данных в Neo4j
Файл nodestore.db содержит определенный размер записей, содержащих информацию о ноде :
- Метка, которая показывает, запись активна;
- Указатель на первое отношение, которое содержит данная нода;
- Указатель на первую свойство, которое содержит данная нода.
Нода не содержит собственного идентификатора. Так как каждая запись в nodestore.db занимает одинаковое количество места, можно рассчитать указатель на ноду.
Файл relationshipstore.db также содержит записи одинакового размера, которые описывают отношения, но они состоят из следующих элементов:
- Метка, которая показывает, запись активна;
- Указатель на ноду, которая содержит это отношение;
- Указатель на ноду, к которой это отношение направлено;
- Вид отношения;
- Указатель на отношение, которое стоит впереди (в пределах данной ноды);
- Указатель на отношение, которое стоит сзади (в пределах данной ноды);
- Указатель на отношение, которое стоит впереди (в пределах Ноды, в которой это отношение направлено);
- Указатель на отношение, которое стоит сзади (в пределах Ноды, в которой это отношение направлено);
- Указатель на первое свойство данного отношения.
Neo4j dump
Create new directories which will hold our data:
$ mkdir -p /tmp/neo4/{data,logs}
Restart the Neo4j container, mount those directories to it:
$ docker run --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latestChanged password for user ‘neo4j’.Directories in use:home: /var/lib/neo4jconfig: /var/lib/neo4j/conflogs: /logsplugins: /var/lib/neo4j/pluginsimport: /var/lib/neo4j/importdata: /var/lib/neo4j/datacertificates: /var/lib/neo4j/certificatesrun: /var/lib/neo4j/run…
Check the data on the host:
$ ll /tmp/neo4/data/databases/total 0drwxr-xr-x 2 7474 7474 720 Jul 27 16:07 neo4j-rw-r — r — 1 7474 7474 0 Jul 27 16:07 store_lockdrwxr-xr-x 3 7474 7474 740 Jul 27 16:07 system
Connect, create a new record:
$ docker exec -ti neo4j cypher-shell -u neo4j -p passneo4j@neo4j> create (test:tobackup);0 rows available after 131 ms, consumed after another 0 msAdded 1 nodes
To create a database dump you first need to stop the instance (as the Community Edition doesn’t have ability for the online backups):
root@771f04312148:/var/lib/neo4j# neo4j-admin dump --database=neo4j --to=/data/backups/The database is in use. Stop database ‘neo4j’ and try again.
So, exit from the container and stop it:
$ docker stop neo4j
Start it over but at this time add the command to prevent Neo4j service from starting:
$ docker run -ti --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latest bashneo4j@6d4e9854bc1d:~$
Create a dump:
neo4j@015ba14bdba2:~$ mkdir /data/backupneo4j@015ba14bdba2:~$ neo4j-admin dump --database=neo4j --to=/data/backup/Done: 34 files, 250.8MiB processed.
Check it:
neo4j@015ba14bdba2:~$ ls -l /data/backup/total 12-rw-r — r — 1 neo4j neo4j 9971 Jul 27 13:46 neo4j.dump
Neo4j dump
Create new directories which will hold our data:
$ mkdir -p /tmp/neo4/{data,logs}
Restart the Neo4j container, mount those directories to it:
$ docker run --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latestChanged password for user ‘neo4j’.Directories in use:home: /var/lib/neo4jconfig: /var/lib/neo4j/conflogs: /logsplugins: /var/lib/neo4j/pluginsimport: /var/lib/neo4j/importdata: /var/lib/neo4j/datacertificates: /var/lib/neo4j/certificatesrun: /var/lib/neo4j/run…
Check the data on the host:
$ ll /tmp/neo4/data/databases/total 0drwxr-xr-x 2 7474 7474 720 Jul 27 16:07 neo4j-rw-r — r — 1 7474 7474 0 Jul 27 16:07 store_lockdrwxr-xr-x 3 7474 7474 740 Jul 27 16:07 system
Connect, create a new record:
$ docker exec -ti neo4j cypher-shell -u neo4j -p passneo4j@neo4j> create (test:tobackup);0 rows available after 131 ms, consumed after another 0 msAdded 1 nodes
To create a database dump you first need to stop the instance (as the Community Edition doesn’t have ability for the online backups):
root@771f04312148:/var/lib/neo4j# neo4j-admin dump --database=neo4j --to=/data/backups/The database is in use. Stop database ‘neo4j’ and try again.
So, exit from the container and stop it:
$ docker stop neo4j
Start it over but at this time add the command to prevent Neo4j service from starting:
$ docker run -ti --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latest bashneo4j@6d4e9854bc1d:~$
Create a dump:
neo4j@015ba14bdba2:~$ mkdir /data/backupneo4j@015ba14bdba2:~$ neo4j-admin dump --database=neo4j --to=/data/backup/Done: 34 files, 250.8MiB processed.
Check it:
neo4j@015ba14bdba2:~$ ls -l /data/backup/total 12-rw-r — r — 1 neo4j neo4j 9971 Jul 27 13:46 neo4j.dump
Relations
A new relationship can be created between any new nodes, or between already existing.
To create a Relation between new nodes — add the :
neo4j@neo4j> create (node3:label3 {key1: “value1”, key2: “value2”}) --> (node4:label4{key1: “value1”, key2: “value2”}) RETURN node3, node4;+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+| node3 | node4 |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+| (:label3 {key1: “value1”, key2: “value2”}) | (:label4 {key1: “value1”, key2: “value2”}) |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+1 row available after 88 ms, consumed after another 8 msAdded 2 nodes, Created 1 relationships, Set 4 properties, Added 2 labels
Check it:
To create a Relation between already existing nodes — use to select those nodes:
neo4j@neo4j> MATCH (node3:label3), (node4:label4) CREATE (node3) --> (node4) RETURN node3, node4;+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+| node3 | node4 |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+| (:label3 {key1: “value1”, key2: “value2”}) | (:label4 {key1: “value1”, key2: “value2”}) |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -+1 row available after 124 ms, consumed after another 9 msCreated 1 relationships
Backup && Restore
Data is stored in the which is actually a symlink to the , see here>>>.
Check directories:
root@65d8061ac13e:/var/lib/neo4j# ls -l /var/lib/neo4j/datalrwxrwxrwx 1 root root 5 Jul 23 09:01 /var/lib/neo4j/data -> /dataroot@65d8061ac13e:/var/lib/neo4j# ls -l /data/total 12drwxrwxrwx 4 neo4j neo4j 4096 Jul 27 11:19 databasesdrwxr-xr-x 2 neo4j neo4j 4096 Jul 27 11:19 dbmsdrwxrwxrwx 4 neo4j neo4j 4096 Jul 27 11:19 transactions
Databases files are stored in the directory, where you can find two default databases — the system and neo4j, which can be found with the :
neo4j@neo4j> show databases;+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — +| name | address | role | requestedStatus | currentStatus | error | default |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — +| “neo4j” | “localhost:7687” | “standalone” | “online” | “online” | “” | TRUE || “system” | “localhost:7687” | “standalone” | “online” | “online” | “” | FALSE |+ — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — +
The system database is used for the… Well, for the system itself, while nedo4j is the default user database.
Cypher-Shell’s parameter support to the rescue!
In order to leverage the query parametrization and speeding-up (again) the import process we can use the cypher-shell-mode that allows using query parameters.
In order to export the data in a cypher-shell compatible format we can execute the following procedure call:
CALL apoc.export.cypher.all({file},{format:'cypher-shell', useOptimizations:{type:'unwind_batch_params',unwindBatchSize: 2}})
That produces the following output script:
:beginCREATE INDEX ON :Bar(first_name,last_name);CREATE INDEX ON :Foo(name);CREATE CONSTRAINT ON (node:Bar) ASSERT (node.name) IS UNIQUE;CREATE CONSTRAINT ON (node:`UNIQUE IMPORT LABEL`) ASSERT (node.`UNIQUE IMPORT ID`) IS UNIQUE;:commitCALL db.awaitIndex(':Foo(name)');CALL db.awaitIndex(':Bar(first_name,last_name)');CALL db.awaitIndex(':Bar(name)');:param rows => :beginUNWIND $rows AS rowCREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Bar;:commit:param rows => :beginUNWIND $rows AS rowCREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Foo;:commit:param rows => :beginUNWIND $rows AS rowCREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Foo;:commit:param rows => :beginUNWIND $rows AS rowCREATE (n:Bar{name: row.name}) SET n += row.properties;:commit:param rows => :beginUNWIND $rows AS rowMATCH (start:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row.start._id})MATCH (end:Bar{name: row.end.name})CREATE (start)-->(end) SET r += row.properties;:commit:beginMATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 2 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;:commit:beginMATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 2 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;:commit:beginMATCH (n:`UNIQUE IMPORT LABEL`) WITH n LIMIT 2 REMOVE n:`UNIQUE IMPORT LABEL` REMOVE n.`UNIQUE IMPORT ID`;:commit:beginDROP CONSTRAINT ON (node:`UNIQUE IMPORT LABEL`) ASSERT (node.`UNIQUE IMPORT ID`) IS UNIQUE;:commit
As you can see, in cypher-shell it’s possible to define a parameter in this way:
:param name => expression
so in our case:
:param rows =>
So we defined a parameter that can be used in a Cypher query with the prefix, in the following way:
UNWIND $rows AS rowCREATE (n:`UNIQUE IMPORT LABEL`{`UNIQUE IMPORT ID`: row._id}) SET n += row.properties SET n:Bar;
In previous versions, the cypher-shell much like Neo4j Browser evaluated those expressions by sending them with a prefixed over the wire to the server to be evaluated by the server-side cypher-engine. That introduced both a network roundtrip per parameter, prohibited their use inside of a client-side transaction and strained the cypher parser even more. That’s why our first experiments with parameters were actually a bit slower than the ones without.Thanks to the Cypher team, cypher-shell gained a client-side expression parser in version 1.1.9 so most of those drawbacks are now gone, and the import speed improved a lot.
The Benchmarks
We used the following dataset (thanks to Alberto de Lazzari for providing that) for our benchmark.
The dataset is composed by:
- 4713605 nodes
- 4549134 relationships
Общие сведения
Основные транзакционные возможности — поддержка ACID и соответствие спецификациям JTA, JTS и XA. Интерфейс программирования приложений для СУБД реализован для многих языков программирования, включая Java, Python, Clojure, Ruby, PHP, также реализовано API в стиле REST
Расширить программный интерфейс можно как с помощью серверных плагинов, так и с помощью неуправляемых расширений (unmanaged extensions); плагины могут добавлять новые ресурсы к REST-интерфейсу для конечных пользователей, а расширения позволяют получить полный контроль над программным интерфейсом, и могут содержать произвольный код, поэтому их следует использовать с осторожностью.
В СУБД используется собственный язык запросов — Cypher, но запросы можно делать и другими способами, например, напрямую через Java API и на языке Gremlin, созданном в проекте с открытым исходным кодом TinkerPop. Cypher является не только языком запросов, но и языком манипулирования данными, так как предоставляет функции CRUD для графового хранилища.
Restore
On the host create a new set of directories — for the second Neo4j instance:
$ mkdir -p /tmp/neo4–2/{data,logs}
Copy the backups directory from the first one:
$ sudo cp -r /tmp/neo4/data/backup/ /tmp/neo4–2/data/
Run the service as usual, mount the , replace ports and its name:
$ docker run — rm — name neo4j-2 — env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect and check the data:
$ docker exec -ti neo4j-2 cypher-shell -u neo4j -p passConnected to Neo4j 4.1.0 at neo4j://localhost:7687 as user neo4j.Type :help for a list of available commands or :exit to exit the shell.Note that Cypher queries must end with a semicolon.neo4j@neo4j> match (n) return n;+ — -+| n |+ — -++ — -+
Okay — nothing found here as this is a brand new database.
Exit from the container, stop it and run over with the :
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest bashneo4j@b0f324cb7c9b:~$
Load the dump to the database with the key as the default neo4j database already present:
neo4j@7bca892e9538:~$ neo4j-admin load --from=/data/backup/neo4j.dump --database=neo4j --forceDone: 34 files, 250.8MiB processed.
Exit, restart container again in the normal way to start the Neo4j process:
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect, check:
neo4j@neo4j> match (n) return n;+ — — — — — — -+| n |+ — — — — — — -+| (:tobackup) |+ — — — — — — -+
Our record is on its place — all done.
Why versioning?
First and foremost, versioning allows us to keep track of change. We can see what has been altered and retrace our steps if necessary.
Another reason for versioning would be for what-if analysis. Whereas keeping track of change shows us historical changes, suggesting a change that hasn’t already occurred allows us to start examining what might happen under certain scenarios and project into the future.
There are many use-cases where you might see versioning in use, for example:
- Identity and Access management — We can keep track of who is accessing what and when, and start to do analysis on any interesting behaviours we should be investigating
- Monitoring changes in networks — Much like the above example, not only can we keep track of what’s been accessed to watch out for unusual behaviour, but we can also do predictive behaviours based on what happens when we make changes and what might the impacts be
- Collaborative working — Think GitHub and other collaborative working tools. We can track changes being made, see when they occurred, and reduce the likelihood of losing contributions.
Restore
On the host create a new set of directories — for the second Neo4j instance:
$ mkdir -p /tmp/neo4–2/{data,logs}
Copy the backups directory from the first one:
$ sudo cp -r /tmp/neo4/data/backup/ /tmp/neo4–2/data/
Run the service as usual, mount the , replace ports and its name:
$ docker run — rm — name neo4j-2 — env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect and check the data:
$ docker exec -ti neo4j-2 cypher-shell -u neo4j -p passConnected to Neo4j 4.1.0 at neo4j://localhost:7687 as user neo4j.Type :help for a list of available commands or :exit to exit the shell.Note that Cypher queries must end with a semicolon.neo4j@neo4j> match (n) return n;+ — -+| n |+ — -++ — -+
Okay — nothing found here as this is a brand new database.
Exit from the container, stop it and run over with the :
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest bashneo4j@b0f324cb7c9b:~$
Load the dump to the database with the key as the default neo4j database already present:
neo4j@7bca892e9538:~$ neo4j-admin load --from=/data/backup/neo4j.dump --database=neo4j --forceDone: 34 files, 250.8MiB processed.
Exit, restart container again in the normal way to start the Neo4j process:
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect, check:
neo4j@neo4j> match (n) return n;+ — — — — — — -+| n |+ — — — — — — -+| (:tobackup) |+ — — — — — — -+
Our record is on its place — all done.
1. Установка Neo4j
Перед запуском Neo4j будет полезно взглянуть внутрь конфигурационного файла neo4j.conf (его расположение в Ubuntu: /etc/neo4j/neo4j.conf). В нём задаются различные параметры для старта СУБД (название базы данных, настройки сети, JVM и т.д.). Для того чтобы Вы могли выполнять задания курса без авторизации при доступе к базе данных, была раскомментирована следующая строчка:
Однако в реальных проектах пренебрегать безопасностью не стоит. Для того, чтобы установить пароль для пользователя neo4j перед самым первым запуском Neo4j, выполните команду:
где вместо введите устанавливаемый пароль (по умолчанию пароль neo4j).
Запуск и остановка Neo4j производится с помощью команды (с аргументом start или stop), набранной в терминале:
или
или
Для того чтобы определить, что Neo4j успешно запущен (наличие сообщения об этом в терминале ещё не гарантирует, что ничего не упало сразу после), можно воспользоваться командой:
Разумеется, т.к. Neo4j реализован на Java, будет обнаружен соответствующий процесс с командой, большая часть которой сознательно опущена (но если рассмотреть её полностью, то можно увидеть параметры, заданные в конфигурационном файле).
Также можно убедиться в успешности запуска, прочитав файл /var/log/neo4j/neo4j.log.
Документация:
Neo4j dump
Create new directories which will hold our data:
$ mkdir -p /tmp/neo4/{data,logs}
Restart the Neo4j container, mount those directories to it:
$ docker run --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latestChanged password for user ‘neo4j’.Directories in use:home: /var/lib/neo4jconfig: /var/lib/neo4j/conflogs: /logsplugins: /var/lib/neo4j/pluginsimport: /var/lib/neo4j/importdata: /var/lib/neo4j/datacertificates: /var/lib/neo4j/certificatesrun: /var/lib/neo4j/run…
Check the data on the host:
$ ll /tmp/neo4/data/databases/total 0drwxr-xr-x 2 7474 7474 720 Jul 27 16:07 neo4j-rw-r — r — 1 7474 7474 0 Jul 27 16:07 store_lockdrwxr-xr-x 3 7474 7474 740 Jul 27 16:07 system
Connect, create a new record:
$ docker exec -ti neo4j cypher-shell -u neo4j -p passneo4j@neo4j> create (test:tobackup);0 rows available after 131 ms, consumed after another 0 msAdded 1 nodes
To create a database dump you first need to stop the instance (as the Community Edition doesn’t have ability for the online backups):
root@771f04312148:/var/lib/neo4j# neo4j-admin dump --database=neo4j --to=/data/backups/The database is in use. Stop database ‘neo4j’ and try again.
So, exit from the container and stop it:
$ docker stop neo4j
Start it over but at this time add the command to prevent Neo4j service from starting:
$ docker run -ti --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latest bashneo4j@6d4e9854bc1d:~$
Create a dump:
neo4j@015ba14bdba2:~$ mkdir /data/backupneo4j@015ba14bdba2:~$ neo4j-admin dump --database=neo4j --to=/data/backup/Done: 34 files, 250.8MiB processed.
Check it:
neo4j@015ba14bdba2:~$ ls -l /data/backup/total 12-rw-r — r — 1 neo4j neo4j 9971 Jul 27 13:46 neo4j.dump
Описание
Cypher — это декларативный язык запросов к графу, который позволяет создать выразительный и эффективный запрос. Cypher — относительно простой, но все же очень мощный язык. Очень сложные запросы к базе данных можно легко выразить через Cypher. Он позволяет писать графические запросы, описывая шаблоны ваших данных. Поскольку графики уже описывают ваш домен, Cypher позволяет сосредоточиться на своем домене, а не теряться в механизме доступа к данным.
Cypher разработан для того, чтобы быть удобным языком запросов, подходящим как для разработчиков, так и тех, кто работает с БД. Его конструкции основаны на английской прозе и опрятной иконографии, которая помогает сделать запросы более понятными. Разработчики попытались оптимизировать язык для чтения, а не для записи.
Будучи декларативным языком, Cypher фокусируется на ясности выражения того, что нужно извлечь из графика, а не о том, как его получить. Это противоречит императивным языкам (Java), языки сценариев (Gremlin), и привязки (JRuby Neo4j). Такой подход делает оптимизацию запросов вопросом реализации БД, а не пользователя, поэтому необходимо, чтобы происходило обновление всех обходов только потому, что изменилась структура физической базы (новые индексы и т. Д.).
Cypher вдохновлен рядом различных подходов и опирается на установленные практики для выразительного запроса. Большинство ключевых слов, таких как WHERE и ORDER BY, основаны на SQL. Соответствие шаблону использует подходы выражения из SPARQL. Некоторые семантики списка были заимствованы из таких языков, как Haskell и Python.
Установка Neo4j
Для наглядного примера разберем установку Neo4j для Ubuntu .
1. Установка JDK
Для того, чтобы установить Neo4j, необходимо сначала выполнить установку Java Development Kit JDK. Для этого обновим список пакетов:
$ sudo apt-get update
Далее установим (JDK)
$ sudo apt-get install default-jdk
2.Добавление репозитория
Вносим ключ Neo4j в менеджер пакетов apt:
$ wget -O — debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add -
Добавляем Neo4j в список исходных кодов apt:
$ echo 'deb http://debian.neo4j.org/repo stable/' >/tmp/neo4j.list $ sudo mv /tmp/neo4j.list /etc/apt/sources.list.d
Обновим менеджер пакетов
$ sudo apt-get update
4. Разрешить удалённый доступ
Откроем файл, который необходимо изменить
$ cd/etc/neo4j $ sudo neo4j.conf
Затем раскомментируем необходимые строчки
dbms.security.auth_enabled=false dbms.connectors.default_listen_address=0.0.0.0
Видео по установке
Более детально и наглядно можно рассмотреть установку Neo4j по видео
Restore
On the host create a new set of directories — for the second Neo4j instance:
$ mkdir -p /tmp/neo4–2/{data,logs}
Copy the backups directory from the first one:
$ sudo cp -r /tmp/neo4/data/backup/ /tmp/neo4–2/data/
Run the service as usual, mount the , replace ports and its name:
$ docker run — rm — name neo4j-2 — env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect and check the data:
$ docker exec -ti neo4j-2 cypher-shell -u neo4j -p passConnected to Neo4j 4.1.0 at neo4j://localhost:7687 as user neo4j.Type :help for a list of available commands or :exit to exit the shell.Note that Cypher queries must end with a semicolon.neo4j@neo4j> match (n) return n;+ — -+| n |+ — -++ — -+
Okay — nothing found here as this is a brand new database.
Exit from the container, stop it and run over with the :
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest bashneo4j@b0f324cb7c9b:~$
Load the dump to the database with the key as the default neo4j database already present:
neo4j@7bca892e9538:~$ neo4j-admin load --from=/data/backup/neo4j.dump --database=neo4j --forceDone: 34 files, 250.8MiB processed.
Exit, restart container again in the normal way to start the Neo4j process:
$ docker run -ti --rm --name neo4j-2 --env NEO4J_AUTH=neo4j/pass -p 7475:7474 -p 7688:7687 -v /tmp/neo4–2/data/:/data -v /tmp/neo4–2/logs/:/logs neo4j:latest
Connect, check:
neo4j@neo4j> match (n) return n;+ — — — — — — -+| n |+ — — — — — — -+| (:tobackup) |+ — — — — — — -+
Our record is on its place — all done.
10 000 узлов и скорость вставки 100 000
Вставьте десять тысяч вершин V
Десять тысяч узлов — анализ производительности вставки узла.jpg
Простой анализ
- Время, затрачиваемое тремя базами данных графа на вставку узлов, практически одинаково, а производительность определяется следующим образом: OrientDB> Neo4J> ArangoDB
- Использование ЦП состоит в том, что использование Neo4J выше, чем у OrentDB, а у ArangoDB есть увеличение в конце, и в сочетании с первым графиком конечный наклон ArangoDB увеличивается, предполагается, что ArangoDB может вставлять наклон узла по мере увеличения количества узлов. Это потому, что ArangoDB вычисляет при хранении узловОднако ось Y скорости вставки узлов отличается по порядку величины от вычисленной позже оси Y. Для ArangoDB стоит пожертвовать производительностью вставки узлов, чтобы улучшить последующую производительность.
- Для использования ОЗУ: ArangoDB> OrientDB> Neo4J
- Использование жесткого диска, OrientDB> Neo4J> ArangoDB
В заключение
На этапе вставки узла:
- ArangoDB строит индекс хеширования, поэтому производительность при вставке узла будет немного ниже, ОЗУ занимает больше всего, а занимаемое пространство для хранения — самое маленькое.
- Neo4J выполняет вычисления с интенсивным использованием ЦП, а степень заполнения оперативной памяти и жесткого диска невысока.
- OrientDB имеет самое короткое время вставки, низкое использование ЦП и ОЗУ. Он имеет преимущество создания индекса дерева BS, но занимает много места на диске. Он хранит данные непосредственно в виде документов без предварительной обработки. Из следующих данных видно, что OrientDB Хотя и ArangoDB, и ArangoDB поддерживают базы данных документов и данные графиков, OrientDB больше фокусируется на хранении данных документов, а не на анализе данных графиков.
Простой анализ
- При вставке ребра требуется длительная последовательность OrientDB> ArangoDB> Neo4J. Из этого можно видеть, что производительность OrientDB без надлежащей предварительной обработки в ссылке узла при вставке отношений значительно отстает от ArangoDB и Neo4J.
- Что касается использования ЦП, Neo4J> OrientDB> ArangoDB
- Использование диска: Neo4J> OrientDB> ArangoDB
В заключение
- В случае вставки края производительность ArangDB все еще немного отстает от Neo4J, но он не так хорош, как ArangoDB с точки зрения использования ЦП, ОЗУ и диска.
- Производительность OrientDB сильно отстает, и оставшееся пространство на диске сильно колеблется при его вставке, что может быть вызвано файлами кеша.
- Слишком большой разрыв в производительности OrientDB при вставке E
- Глубина соседства 1
- Используется алгоритм в ширину, встроенный в три базы данных графов.
Neo4j dump
Create new directories which will hold our data:
$ mkdir -p /tmp/neo4/{data,logs}
Restart the Neo4j container, mount those directories to it:
$ docker run --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latestChanged password for user ‘neo4j’.Directories in use:home: /var/lib/neo4jconfig: /var/lib/neo4j/conflogs: /logsplugins: /var/lib/neo4j/pluginsimport: /var/lib/neo4j/importdata: /var/lib/neo4j/datacertificates: /var/lib/neo4j/certificatesrun: /var/lib/neo4j/run…
Check the data on the host:
$ ll /tmp/neo4/data/databases/total 0drwxr-xr-x 2 7474 7474 720 Jul 27 16:07 neo4j-rw-r — r — 1 7474 7474 0 Jul 27 16:07 store_lockdrwxr-xr-x 3 7474 7474 740 Jul 27 16:07 system
Connect, create a new record:
$ docker exec -ti neo4j cypher-shell -u neo4j -p passneo4j@neo4j> create (test:tobackup);0 rows available after 131 ms, consumed after another 0 msAdded 1 nodes
To create a database dump you first need to stop the instance (as the Community Edition doesn’t have ability for the online backups):
root@771f04312148:/var/lib/neo4j# neo4j-admin dump --database=neo4j --to=/data/backups/The database is in use. Stop database ‘neo4j’ and try again.
So, exit from the container and stop it:
$ docker stop neo4j
Start it over but at this time add the command to prevent Neo4j service from starting:
$ docker run -ti --rm --name neo4j --env NEO4J_AUTH=neo4j/pass -p 7474:7474 -p 7687:7687 -v /tmp/neo4/data/:/data -v /tmp/neo4/logs/:/logs neo4j:latest bashneo4j@6d4e9854bc1d:~$
Create a dump:
neo4j@015ba14bdba2:~$ mkdir /data/backupneo4j@015ba14bdba2:~$ neo4j-admin dump --database=neo4j --to=/data/backup/Done: 34 files, 250.8MiB processed.
Check it:
neo4j@015ba14bdba2:~$ ls -l /data/backup/total 12-rw-r — r — 1 neo4j neo4j 9971 Jul 27 13:46 neo4j.dump