ΠΡΠ΅ΠΌ ΠΏΡΠΈΠ²Π΅Ρ. ΠΡ ΡΠ°Π·ΡΠ°Π±Π°ΡΡΠ²Π°Π΅ΠΌ ΠΏΡΠΎΠ΄ΡΠΊΡ Π΄Π»Ρ Π°Π½Π°Π»ΠΈΠ·Π° ΠΎΡΡΠ»Π°ΠΉΠ½-ΡΡΠ°ΡΠΈΠΊΠ°. Π ΠΏΡΠΎΠ΅ΠΊΡΠ΅ Π΅ΡΡΡ Π·Π°Π΄Π°ΡΠ°, ΡΠ²ΡΠ·Π°Π½Π½Π°Ρ ΡΠΎ ΡΡΠ°ΡΠΈΡΡΠΈΡΠ΅ΡΠΊΠΈΠΌ Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ ΠΏΡΡΠ΅ΠΉ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ ΠΏΠΎΡΠ΅ΡΠΈΡΠ΅Π»Π΅ΠΉ ΠΏΠΎ ΠΎΠ±Π»Π°ΡΡΡΠΌ.
Π ΡΠ°ΠΌΠΊΠ°Ρ ΡΡΠΎΠΉ Π·Π°Π΄Π°ΡΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ ΠΌΠΎΠ³ΡΡ Π·Π°Π΄Π°Π²Π°ΡΡ ΡΠΈΡΡΠ΅ΠΌΠ΅ Π·Π°ΠΏΡΠΎΡΡ ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ Π²ΠΈΠ΄Π°:
- ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ΅ΡΠΈΡΠ΅Π»Π΅ΠΉ ΠΏΡΠΎΡΠ»ΠΎ ΠΈΠ· ΠΎΠ±Π»Π°ΡΡΠΈ "A" Π² ΠΎΠ±Π»Π°ΡΡΡ "Π";
- ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ΅ΡΠΈΡΠ΅Π»Π΅ΠΉ ΠΏΡΠΎΡΠ»ΠΎ ΠΈΠ· ΠΎΠ±Π»Π°ΡΡΠΈ "A" Π² ΠΎΠ±Π»Π°ΡΡΡ "Π" ΡΠ΅ΡΠ΅Π· ΠΎΠ±Π»Π°ΡΡΡ "C", Π° Π·Π°ΡΠ΅ΠΌ ΡΠ΅ΡΠ΅Π· ΠΎΠ±Π»Π°ΡΡΡ "Π";
- ΡΠΊΠΎΠ»ΡΠΊΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π·Π°Π½ΡΠ»ΠΎ ΠΏΡΠΎΡ ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΡΠ΅ΡΠΈΡΠ΅Π»Ρ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ° ΠΈΠ· ΠΎΠ±Π»Π°ΡΡΠΈ "Π" Π² ΠΎΠ±Π»Π°ΡΡΡ "Π".
ΠΈ Π΅ΡΠ΅ ΡΡΠ΄ ΠΏΠΎΠ΄ΠΎΠ±Π½ΡΡ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ².
ΠΠ²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΡΠ΅ΡΠΈΡΠ΅Π»Ρ ΠΏΠΎ ΠΎΠ±Π»Π°ΡΡΡΠΌ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΡΠΎΠ±ΠΎΠΉ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½Π½ΡΠΉ Π³ΡΠ°Ρ. ΠΠΎΡΠΈΡΠ°Π² ΠΈΠ½ΡΠ΅ΡΠ½Π΅ΡΡ, Ρ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ», ΡΡΠΎ Π³ΡΠ°ΡΠΎΠ²ΡΠ΅ Π‘Π£ΠΠ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ ΠΈ Π΄Π»Ρ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ ΠΎΡΡΠ΅ΡΠΎΠ². Π£ ΠΌΠ΅Π½Ρ ΠΏΠΎΡΠ²ΠΈΠ»ΠΎΡΡ ΠΆΠ΅Π»Π°Π½ΠΈΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ ΠΊΠ°ΠΊ Π±ΡΠ΄ΡΡ ΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ Ρ ΠΏΠΎΠ΄ΠΎΠ±Π½ΡΠΌΠΈ Π·Π°ΠΏΡΠΎΡΠ°ΠΌΠΈ Π³ΡΠ°ΡΠΎΠ²ΡΠ΅ Π‘Π£ΠΠ (TL;DR; ΠΏΠ»ΠΎΡ ΠΎ).
Π― Π²ΡΠ±ΡΠ°Π» Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π‘Π£ΠΠ
- Π±ΡΠΊΠ΅Π½Π΄ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° BerkeleyDB, Apache Cassandra, Scylla;
- ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΠΈΠ½Π΄Π΅ΠΊΡΡ ΠΌΠΎΠΆΠ½ΠΎ Ρ ΡΠ°Π½ΠΈΡΡ Π² Lucene, Elasticsearch, Solr.
ΠΠ²ΡΠΎΡΡ JanusGraph ΠΏΠΈΡΡΡ, ΡΡΠΎ ΠΎΠ½Π° ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΈΡ ΠΊΠ°ΠΊ Π΄Π»Ρ OLTP, ΡΠ°ΠΊ ΠΈ Π΄Π»Ρ OLAP.
Π― ΡΠ°Π±ΠΎΡΠ°Π» Ρ BerkeleyDB, Apache Cassandra, Scylla ΠΈ ES, ΠΊΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Π΄Π°Π½Π½ΡΠ΅ ΠΏΡΠΎΠ΄ΡΠΊΡΡ ΡΠ°ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π² Π½Π°ΡΠΈΡ ΡΠΈΡΡΠ΅ΠΌΠ°Ρ , ΠΏΠΎΡΡΠΎΠΌΡ Ρ Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΌΠΎΠΌ ΡΠΌΠΎΡΡΠ΅Π» Π½Π° ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΠΎΠΉ Π³ΡΠ°ΡΠΎΠ²ΠΎΠΉ Π‘Π£ΠΠ. ΠΠ½Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π»ΡΡ ΡΡΡΠ°Π½Π½ΡΠΌ Π²ΡΠ±ΠΎΡ BerkeleyDB, Π° Π½Π΅ RocksDB, Π½ΠΎ, Π²Π΅ΡΠΎΡΡΠ½ΠΎ, ΡΡΠΎ ΡΠ²ΡΠ·Π°Π½ΠΎ Ρ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡΠΌ ΠΊ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡΠΌ. Π Π»ΡΠ±ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, Π΄Π»Ρ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΠΎΠ³ΠΎ, ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠ²ΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΏΡΠ΅Π΄Π»Π°Π³Π°Π΅ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π±ΡΠΊΠ΅Π½Π΄ Π½Π° Cassandra ΠΈΠ»ΠΈ Scylla.
Neo4j Ρ Π½Π΅ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π», ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π΄Π»Ρ ΠΊΠ»Π°ΡΡΠ΅ΡΠΈΠ·Π°ΡΠΈΠΈ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΠΊΠΎΠΌΠΌΠ΅ΡΡΠ΅ΡΠΊΠ°Ρ Π²Π΅ΡΡΠΈΡ, ΡΠΎ Π΅ΡΡΡ ΠΏΡΠΎΠ΄ΡΠΊΡ Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΎΡΠΊΡΡΡΡΠΌ.
ΠΡΠ°ΡΠΎΠ²ΡΠ΅ Π‘Π£ΠΠ Π³ΠΎΠ²ΠΎΡΡΡ: "ΠΡΠ»ΠΈ ΡΡΠΎ-ΡΠΎ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΠ°ΠΊ Π³ΡΠ°Ρ β ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΠΉΡΠ΅ ΡΡΠΎ ΠΊΠ°ΠΊ Π³ΡΠ°Ρ!" β ΠΊΡΠ°ΡΠΎΡΠ°!
Π‘Π½Π°ΡΠ°Π»Π° Ρ Π½Π°ΡΠΈΡΠΎΠ²Π°Π» Π³ΡΠ°Ρ, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΠΎΡ ΠΏΡΡΠΌ ΠΏΠΎ ΠΊΠ°Π½ΠΎΠ½Π°ΠΌ Π³ΡΠ°ΡΠΎΠ²ΡΡ Π‘Π£ΠΠ ΡΠ΄Π΅Π»Π°Π½:
ΠΡΡΡ ΡΡΡΠ½ΠΎΡΡΡ Zone
, ΠΎΡΠ²Π΅ΡΠ°ΡΡΠ°Ρ Π·Π° ΠΎΠ±Π»Π°ΡΡΡ. ΠΡΠ»ΠΈ ZoneStep
ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠΈΡ ΡΡΠΎΠΉ Zone
, ΡΠΎ ΠΎΠ½ Π½Π° Π½Π΅Π΅ ΡΡΡΠ»Π°Π΅ΡΡΡ. ΠΠ° ΡΡΡΠ½ΠΎΡΡΠΈ Area
, ZoneTrack
, Person
Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π΅ ΠΎΠ±ΡΠ°ΡΠ°ΠΉΡΠ΅, ΠΎΠ½ΠΈ ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ Π΄ΠΎΠΌΠ΅Π½Ρ ΠΈ Π² ΡΠ°ΠΌΠΊΠ°Ρ
ΡΠ΅ΡΡΠ° Π½Π΅ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡΡΡ. ΠΡΠΎΠ³ΠΎ, ΠΊ ΡΠ°ΠΊΠΎΠΉ Π³ΡΠ°ΡΠΎΠ²ΠΎΠΉ ΡΡΡΡΠΊΡΡΡΠ΅ Π·Π°ΠΏΡΠΎΡ ΠΏΠΎΠΈΡΠΊΠ° ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ³Π»ΡΠ΄Π΅Π» Π±Ρ ΠΊΠ°ΠΊ:
g.V().hasLabel('Zone').has('id',0).in_()
.repeat(__.out()).until(__.out().hasLabel('Zone').has('id',19)).count().next()
Π§ΡΠΎ Π½Π° ΡΡΡΡΠΊΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ: Π½Π°ΠΉΠ΄ΠΈ Zone Ρ ID=0, Π²ΠΎΠ·ΡΠΌΠΈ Π²ΡΠ΅ Π²Π΅ΡΡΠΈΠ½Ρ, ΠΎΡ ΠΊΠΎΡΠΎΡΡΡ ΠΊ Π½Π΅ΠΉ ΠΈΠ΄Π΅Ρ ΡΠ΅Π±ΡΠΎ (ZoneStep), ΡΠΎΠΏΠ°ΠΉ Π±Π΅Π· Π²ΠΎΠ·Π²ΡΠ°ΡΠ° Π½Π°Π·Π°Π΄ ΠΏΠΎΠΊΠ° Π½Π΅ Π½Π°ΠΉΠ΄Π΅ΡΡ ΡΠ°ΠΊΠΈΠ΅ ZoneStep, ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ ΠΈΠ΄Π΅Ρ ΡΠ΅Π±ΡΠΎ Π² Zone Ρ ID=19, ΠΏΠΎΡΡΠΈΡΠ°ΠΉ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠ°ΠΊΠΈΡ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ.
Π― Π½Π΅ ΠΏΡΠ΅ΡΠ΅Π½Π΄ΡΡ Π½Π° Π·Π½Π°Π½ΠΈΠ΅ Π²ΡΠ΅ ΡΠΎΠ½ΠΊΠΎΡΡΠ΅ΠΉ ΠΏΠΎΠΈΡΠΊΠ° Π½Π° Π³ΡΠ°ΡΠ°Ρ
, Π½ΠΎ Π΄Π°Π½Π½ΡΠΉ Π·Π°ΠΏΡΠΎΡ Π±ΡΠ» ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π½ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π²ΠΎΡ ΡΡΠΎΠΉ ΠΊΠ½ΠΈΠ³ΠΈ (
Π― Π·Π°Π³ΡΡΠ·ΠΈΠ» 50 ΡΡΡΡΡ ΡΡΠ΅ΠΊΠΎΠ² Π΄Π»ΠΈΠ½ΠΎΠΉ ΠΎΡ 3 Π΄ΠΎ 20 ΡΠΎΡΠ΅ΠΊ Π² Π³ΡΠ°ΡΠΎΠ²ΡΡ Π±Π°Π·Ρ JanusGraph, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π±ΡΠΊΠ΅Π½Π΄ BerkeleyDB, ΡΠΎΠ·Π΄Π°Π» ΠΈΠ½Π΄Π΅ΠΊΡΡ ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ
Π‘ΠΊΡΠΈΠΏΡ Π΄Π»Ρ Π·Π°Π³ΡΡΠ·ΠΊΠΈ Π½Π° Python:
from random import random
from time import time
from init import g, graph
if __name__ == '__main__':
points = []
max_zones = 19
zcache = dict()
for i in range(0, max_zones + 1):
zcache[i] = g.addV('Zone').property('id', i).next()
startZ = zcache[0]
endZ = zcache[max_zones]
for i in range(0, 10000):
if not i % 100:
print(i)
start = g.addV('ZoneStep').property('time', int(time())).next()
g.V(start).addE('belongs').to(startZ).iterate()
while True:
pt = g.addV('ZoneStep').property('time', int(time())).next()
end_chain = random()
if end_chain < 0.3:
g.V(pt).addE('belongs').to(endZ).iterate()
g.V(start).addE('goes').to(pt).iterate()
break
else:
zone_id = int(random() * max_zones)
g.V(pt).addE('belongs').to(zcache[zone_id]).iterate()
g.V(start).addE('goes').to(pt).iterate()
start = pt
count = g.V().count().next()
print(count)
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»Π°ΡΡ VM c 4 ΡΠ΄ΡΠ°ΠΌΠΈ ΠΈ 16 GB RAM Π½Π° SSD. JanusGraph Π±ΡΠ» ΡΠ°Π·Π²Π΅ΡΠ½ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π²ΠΎΡ ΡΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ:
docker run --name janusgraph -p8182:8182 janusgraph/janusgraph:latest
Π ΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ Π΄Π°Π½Π½ΡΠ΅ ΠΈ ΠΈΠ½Π΄Π΅ΠΊΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π΄Π»Ρ ΠΏΠΎΠΈΡΠΊΠ° ΠΏΠΎ ΡΠΎΡΠ½ΠΎΠΌΡ ΡΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΡ Ρ ΡΠ°Π½ΡΡΡΡ Π² BerkeleyDB. ΠΡΠΏΠΎΠ»Π½ΠΈΠ² Π·Π°ΠΏΡΠΎΡ, ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΠΉ ΡΠ°Π½Π΅Π΅, Ρ ΠΏΠΎΠ»ΡΡΠΈΠ» Π²ΡΠ΅ΠΌΡ ΡΠ°Π²Π½ΠΎΠ΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ Π΄Π΅ΡΡΡΠΊΠ°ΠΌ ΡΠ΅ΠΊΡΠ½Π΄.
ΠΠ°ΠΏΡΡΡΠΈΠ² 4 Π²ΡΡΠ΅ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΡ ΡΠΊΡΠΈΠΏΡΠ° Π² ΠΏΠ°ΡΠ°Π»Π»Π΅Π»Ρ, ΠΌΠ½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ ΠΏΡΠ΅Π²ΡΠ°ΡΠΈΡΡ Π‘Π£ΠΠ Π² ΡΡΠΊΠ²Ρ Ρ Π²Π΅ΡΠ΅Π»ΡΠΌ ΠΏΠΎΡΠΎΠΊΠΎΠΌ ΡΡΠ΅ΠΊΡΡΠ΅ΠΉΡΠΎΠ² Java (Π° ΠΌΡ Π²ΡΠ΅ Π»ΡΠ±ΠΈΠΌ ΡΠΈΡΠ°ΡΡ ΡΡΠ΅ΠΊΡΡΠ΅ΠΉΡΡ Java) Π² Π»ΠΎΠ³Π°Ρ Docker.
ΠΠΎΡΠ°Π·ΠΌΡΡΠ»ΡΠ², Ρ ΡΠ΅ΡΠΈΠ» ΡΠΏΡΠΎΡΡΠΈΡΡ ΡΡ Π΅ΠΌΡ Π³ΡΠ°ΡΠ° Π΄ΠΎ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΉ:
Π Π΅ΡΠΈΠ², ΡΡΠΎ ΠΏΠΎΠΈΡΠΊ ΠΏΠΎ Π°ΡΡΠΈΠ±ΡΡΠ°ΠΌ ΡΡΡΠ½ΠΎΡΡΠΈ Π±ΡΠ΄Π΅Ρ Π±ΡΡΡΡΠ΅Π΅, ΡΠ΅ΠΌ ΠΏΠΎΠΈΡΠΊ ΠΏΠΎ ΡΠ΅Π±ΡΠ°ΠΌ. Π ΠΈΡΠΎΠ³Π΅ ΠΌΠΎΠΉ Π·Π°ΠΏΡΠΎΡ ΠΏΡΠ΅Π²ΡΠ°ΡΠΈΠ»ΡΡ Π² ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ:
g.V().hasLabel('ZoneStep').has('id',0).repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',19)).count().next()
Π§ΡΠΎ Π½Π° ΡΡΡΡΠΊΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ: Π½Π°ΠΉΠ΄ΠΈ ZoneStep Ρ ID=0, ΡΠΎΠΏΠ°ΠΉ Π±Π΅Π· Π²ΠΎΠ·Π²ΡΠ°ΡΠ° Π½Π°Π·Π°Π΄ ΠΏΠΎΠΊΠ° Π½Π΅ Π½Π°ΠΉΠ΄Π΅ΡΡ ZoneStep Ρ ID=19, ΠΏΠΎΡΡΠΈΡΠ°ΠΉ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠ°ΠΊΠΈΡ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ.
Π‘ΠΊΡΠΈΠΏΡ Π·Π°Π³ΡΡΠ·ΠΊΠΈ, ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΠΉ Π²ΡΡΠ΅, Ρ ΡΠΎΠΆΠ΅ ΡΠΏΡΠΎΡΡΠΈΠ», Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ Π½Π΅ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ Π»ΠΈΡΠ½ΠΈΡ ΡΠ²ΡΠ·Π΅ΠΉ, ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²ΡΠΈΡΡ Π°ΡΡΠΈΠ±ΡΡΠ°ΠΌΠΈ.
ΠΠ°ΠΏΡΠΎΡ Π²ΡΠ΅ Π΅ΡΠ΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ»ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ΅ΠΊΡΠ½Π΄, ΡΡΠΎ Π±ΡΠ»ΠΎ ΡΠΎΠ²Π΅ΡΡΠ΅Π½Π½ΠΎ Π½Π΅ΠΏΡΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎ Π΄Π»Ρ Π½Π°ΡΠ΅ΠΉ Π·Π°Π΄Π°ΡΠΈ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π΄Π»Ρ ΡΠ΅Π»Π΅ΠΉ AdHoc Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΠΎΠ³ΠΎ Π²ΠΈΠ΄Π° ΡΡΠΎ ΡΠΎΠ²ΡΠ΅ΠΌ Π½Π΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΈΠ»ΠΎ.
Π― ΠΏΠΎΠΏΡΠΎΠ±ΠΎΠ²Π°Π» ΡΠ°Π·Π²Π΅ΡΠ½ΡΡΡ JanusGraph Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Scylla, ΠΊΠ°ΠΊ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π±ΡΡΡΡΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Cassandra, Π½ΠΎ ΡΡΠΎ ΡΠΎΠΆΠ΅ Π½Π΅ ΠΏΡΠΈΠ²Π΅Π»ΠΎ ΠΊΠ°ΠΊΠΈΠΌ-ΡΠΎ ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΡΠΌ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡΠΌ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ.
Π’Π°ΠΊΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ, Π½Π΅ΡΠΌΠΎΡΡΡ Π½Π° ΡΠΎ, ΡΡΠΎ "ΡΡΠΎ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΠ°ΠΊ Π³ΡΠ°Ρ", ΠΌΠ½Π΅ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ Π·Π°ΡΡΠ°Π²ΠΈΡΡ Π³ΡΠ°ΡΠΎΠ²ΡΡ Π‘Π£ΠΠ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΡΠΎ Π±ΡΡΡΡΠΎ. ΠΠΏΠΎΠ»Π½Π΅ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Ρ, ΡΡΠΎ Ρ ΡΠ΅Π³ΠΎ-ΡΠΎ Π½Π΅ Π·Π½Π°Ρ ΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΡΡΠ°Π²ΠΈΡΡ JanusGraph Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΡΡΠΎΡ ΠΏΠΎΠΈΡΠΊ Π·Π° Π΄ΠΎΠ»ΠΈ ΡΠ΅ΠΊΡΠ½Π΄Ρ, ΠΎΠ΄Π½Π°ΠΊΠΎ, ΠΌΠ½Π΅ ΡΡΠΎ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΠ΅ΡΠΈΡΡ Π·Π°Π΄Π°ΡΡ Π²ΡΠ΅ ΡΠ°Π²Π½ΠΎ Π±ΡΠ»ΠΎ Π½ΡΠΆΠ½ΠΎ, Ρ Π½Π°ΡΠ°Π» Π΄ΡΠΌΠ°ΡΡ ΠΎ JOIN-Π°Ρ ΠΈ Pivot-Π°Ρ ΡΠ°Π±Π»ΠΈΡ, ΡΡΠΎ Π½Π΅ Π²Π½ΡΡΠ°Π»ΠΎ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΌΠ° Ρ ΡΠΎΡΠΊΠΈ Π·ΡΠ΅Π½ΠΈΡ ΠΈΠ·ΡΡΠ½ΠΎΡΡΠΈ, Π½ΠΎ ΠΌΠΎΠ³Π»ΠΎ Π±ΡΡΡ Π²ΠΏΠΎΠ»Π½Π΅ ΡΠ°Π±ΠΎΡΠΈΠΌ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠΌ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅.
Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΎΠ΅ΠΊΡΠ΅ ΡΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Apache ClickHouse, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΡΠ΅ΡΠΈΠ» ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ ΡΠ²ΠΎΠΈ ΠΈΠ·ΡΡΠΊΠ°Π½ΠΈΡ Π½Π° ΡΡΠΎΠΉ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΎΠΉ Π‘Π£ΠΠ.
Π Π°Π·Π²Π΅ΡΠ½ΡΠ» ClickHouse ΠΏΠΎ ΠΏΡΠΎΡΡΠΎΠΌΡ ΡΠ΅ΡΠ΅ΠΏΡΡ:
sudo docker run -d --name clickhouse_1
--ulimit nofile=262144:262144
-v /opt/clickhouse/log:/var/log/clickhouse-server
-v /opt/clickhouse/data:/var/lib/clickhouse
yandex/clickhouse-server
Π‘ΠΎΠ·Π΄Π°Π» Π² Π½Π΅ΠΌ ΠΠ ΠΈ ΡΠ°Π±Π»ΠΈΡΡ Π²ΠΈΠ΄Π°:
CREATE TABLE
db.steps (`area` Int64, `when` DateTime64(1, 'Europe/Moscow') DEFAULT now64(), `zone` Int64, `person` Int64)
ENGINE = MergeTree() ORDER BY (area, zone, person) SETTINGS index_granularity = 8192
ΠΠ°ΠΏΠΎΠ»Π½ΠΈΠ» Π΅Π΅ Π΄Π°Π½Π½ΡΠΌΠΈ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΡΠΊΡΠΈΠΏΡΠΎΠΌ:
from time import time
from clickhouse_driver import Client
from random import random
client = Client('vm-12c2c34c-df68-4a98-b1e5-a4d1cef1acff.domain',
database='db',
password='secret')
max = 20
for r in range(0, 100000):
if r % 1000 == 0:
print("CNT: {}, TS: {}".format(r, time()))
data = [{
'area': 0,
'zone': 0,
'person': r
}]
while True:
if random() < 0.3:
break
data.append({
'area': 0,
'zone': int(random() * (max - 2)) + 1,
'person': r
})
data.append({
'area': 0,
'zone': max - 1,
'person': r
})
client.execute(
'INSERT INTO steps (area, zone, person) VALUES',
data
)
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π²ΡΡΠ°Π²ΠΊΠΈ ΠΈΠ΄ΡΡ Π±Π°ΡΡΠ°ΠΌΠΈ, Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π±ΡΠ»ΠΎ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΡΡΡΡΠ΅Π΅, ΡΠ΅ΠΌ Π΄Π»Ρ JanusGraph.
Π‘ΠΊΠΎΠ½ΡΡΡΡΠΈΡΠΎΠ²Π°Π» Π΄Π²Π° Π·Π°ΠΏΡΠΎΡΠ° Ρ ΠΏΠΎΠΌΠΎΡΡΡ JOIN. ΠΠ»Ρ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Π° ΠΈΠ· ΡΠΎΡΠΊΠΈ A Π² ΡΠΎΡΠΊΡ Π:
SELECT s1.person AS person,
s1.zone,
s1.when,
s2.zone,
s2.when
FROM
(SELECT *
FROM steps
WHERE (area = 0)
AND (zone = 0)) AS s1 ANY INNER JOIN
(SELECT *
FROM steps AS s2
WHERE (area = 0)
AND (zone = 19)) AS s2 USING person
WHERE s1.when <= s2.when
ΠΠ»Ρ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Π° ΡΠ΅ΡΠ΅Π· 3 ΡΠΎΡΠΊΠΈ:
SELECT s3.person,
s1z,
s1w,
s2z,
s2w,
s3.zone,
s3.when
FROM
(SELECT s1.person AS person,
s1.zone AS s1z,
s1.when AS s1w,
s2.zone AS s2z,
s2.when AS s2w
FROM
(SELECT *
FROM steps
WHERE (area = 0)
AND (zone = 0)) AS s1 ANY INNER JOIN
(SELECT *
FROM steps AS s2
WHERE (area = 0)
AND (zone = 3)) AS s2 USING person
WHERE s1.when <= s2.when) p ANY INNER JOIN
(SELECT *
FROM steps
WHERE (area = 0)
AND (zone = 19)) AS s3 USING person
WHERE p.s2w <= s3.when
ΠΠ°ΠΏΡΠΎΡΡ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, Π²ΡΠ³Π»ΡΠ΄ΡΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΡΡΡΠ°ΡΠ½ΠΎ, Π΄Π»Ρ ΡΠ΅Π°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π΄Π΅Π»Π°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΡ ΠΎΠ±Π²ΡΠ·ΠΊΡ-Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡ. ΠΠ΄Π½Π°ΠΊΠΎ, ΠΎΠ½ΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΈ ΡΠ°Π±ΠΎΡΠ°ΡΡ Π±ΡΡΡΡΠΎ. Π ΠΏΠ΅ΡΠ²ΡΠΉ ΠΈ Π²ΡΠΎΡΠΎΠΉ Π·Π°ΠΏΡΠΎΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΠΌΠ΅Π½Π΅Π΅ ΡΠ΅ΠΌ Π·Π° 0.1 ΡΠ΅ΠΊ. ΠΠΎΡ ΠΏΡΠΈΠΌΠ΅Ρ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ ΠΈΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° Π΄Π»Ρ count(*) ΠΏΡΠΎΡ ΠΎΠ΄Π° ΠΏΠΎ 3ΠΌ ΡΠΎΡΠΊΠ°ΠΌ:
SELECT count(*)
FROM
(
SELECT
s1.person AS person,
s1.zone AS s1z,
s1.when AS s1w,
s2.zone AS s2z,
s2.when AS s2w
FROM
(
SELECT *
FROM steps
WHERE (area = 0) AND (zone = 0)
) AS s1
ANY INNER JOIN
(
SELECT *
FROM steps AS s2
WHERE (area = 0) AND (zone = 3)
) AS s2 USING (person)
WHERE s1.when <= s2.when
) AS p
ANY INNER JOIN
(
SELECT *
FROM steps
WHERE (area = 0) AND (zone = 19)
) AS s3 USING (person)
WHERE p.s2w <= s3.when
ββcount()ββ
β 11592 β
βββββββββββ
1 rows in set. Elapsed: 0.068 sec. Processed 250.03 thousand rows, 8.00 MB (3.69 million rows/s., 117.98 MB/s.)
ΠΠ°ΠΌΠ΅ΡΠ°Π½ΠΈΠ΅ ΠΏΡΠΎ IOPS. ΠΡΠΈ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π΄Π°Π½Π½ΡΡ , JanusGraph Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π» Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ Π²ΡΡΠΎΠΊΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ IOPS (1000-1300 Π΄Π»Ρ ΡΠ΅ΡΡΡΠ΅Ρ ΠΏΠΎΡΠΎΠΊΠΎΠ² Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΠΌΠΈ), Π° IOWAIT Π±ΡΠ» Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ Π²ΡΡΠΎΠΊΠΈΠΌ. Π ΡΠΎ ΠΆΠ΅ Π²ΡΠ΅ΠΌΡ, ClickHouse Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π» ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΡΡ Π½Π°Π³ΡΡΠ·ΠΊΡ Π½Π° Π΄ΠΈΡΠΊΠΎΠ²ΡΡ ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΡ.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΡ ΡΠ΅ΡΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ClickHouse Π΄Π»Ρ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΡΡΠΎΠ³ΠΎ ΡΠΈΠΏΠ°. ΠΡ Π²ΡΠ΅Π³Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΅ΡΠ΅ Π±ΠΎΠ»ΡΡΠ΅ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ Π·Π°ΠΏΡΠΎΡΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΌΠ°ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΠ΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΈ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΠΈΠ·Π°ΡΠΈΡ, Π²ΡΠΏΠΎΠ»Π½ΡΡ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΠΏΠΎΡΠΎΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Apache Flink ΠΏΠ΅ΡΠ΅Π΄ Π·Π°Π³ΡΡΠ·ΠΊΠΎΠΉ ΠΈΡ Π² ClickHouse.
ΠΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ Π½Π°ΡΡΠΎΠ»ΡΠΊΠΎ Ρ ΠΎΡΠΎΡΠ°, ΡΡΠΎ Π½Π°ΠΌ, Π²Π΅ΡΠΎΡΡΠ½ΠΎ, Π΄Π°ΠΆΠ΅ Π½Π΅ ΠΏΡΠΈΠ΄Π΅ΡΡΡ Π΄ΡΠΌΠ°ΡΡ ΠΎ pivot-Π°Ρ ΡΠ°Π±Π»ΠΈΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΡΠΌΠΈ ΡΡΠ΅Π΄ΡΡΠ²Π°ΠΌΠΈ. Π Π°Π½Π΅Π΅, Π½Π°ΠΌ ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΠ»ΠΎΡΡ Π΄Π΅Π»Π°ΡΡ pivot-Ρ Π΄Π°Π½Π½ΡΡ , ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌΡΡ ΠΈΠ· Vertica ΡΠ΅ΡΠ΅Π· Π²ΡΠ³ΡΡΠ·ΠΊΡ Π² Apache Parquet.
Π ΡΠΎΠΆΠ°Π»Π΅Π½ΠΈΡ, ΠΎΡΠ΅ΡΠ΅Π΄Π½Π°Ρ ΠΏΠΎΠΏΡΡΠΊΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π³ΡΠ°ΡΠΎΠ²ΠΎΠΉ Π‘Π£ΠΠ Π½Π΅ ΡΠ²Π΅Π½ΡΠ°Π»Π°ΡΡ ΡΡΠΏΠ΅Ρ ΠΎΠΌ. Π― Π½Π΅ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ», ΡΡΠΎ Ρ JanusGraph Π΄ΡΡΠΆΠ΅Π»ΡΠ±Π½Π°Ρ ΡΠΊΠΎΡΠΈΡΡΠ΅ΠΌΠ°, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π±ΡΡΡΡΠΎ ΠΎΡΠ²ΠΎΠΈΡΡΡΡ Ρ ΠΏΡΠΎΠ΄ΡΠΊΡΠΎΠΌ. ΠΡΠΈ ΡΡΠΎΠΌ Π΄Π»Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΡΠΈΠΌΠ΅Π½ΡΠ΅ΡΡΡ ΡΡΠ°Π΄ΠΈΡΠΈΠΎΠ½Π½ΡΠΉ Java-way, ΠΊΠΎΡΠΎΡΡΠΉ Π»ΡΠ΄Π΅ΠΉ Ρ Java Π½Π΅ Π·Π½Π°ΠΊΠΎΠΌΡΡ Π·Π°ΡΡΠ°Π²ΠΈΡ ΠΏΠ»Π°ΠΊΠ°ΡΡ ΠΊΡΠΎΠ²Π°Π²ΡΠΌΠΈ ΡΠ»Π΅Π·Π°ΠΌΠΈ:
host: 0.0.0.0
port: 8182
threadPoolWorker: 1
gremlinPool: 8
scriptEvaluationTimeout: 30000
channelizer: org.janusgraph.channelizers.JanusGraphWsAndHttpChannelizer
graphManager: org.janusgraph.graphdb.management.JanusGraphManager
graphs: {
ConfigurationManagementGraph: conf/janusgraph-cql-configurationgraph.properties,
airlines: conf/airlines.properties
}
scriptEngines: {
gremlin-groovy: {
plugins: { org.janusgraph.graphdb.tinkerpop.plugin.JanusGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
org.apache.tinkerpop.gremlin.tinkergraph.jsr223.TinkerGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {classImports: [java.lang.Math], methodImports: [java.lang.Math#*]},
org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {files: [scripts/airline-sample.groovy]}}}}
serializers:
# GraphBinary is here to replace Gryo and Graphson
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: true }}
# Gryo and Graphson, latest versions
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
# Older serialization versions for backwards compatibility:
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0, config: {ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistryV1d0] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistryV1d0] }}
processors:
- { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
- { className: org.apache.tinkerpop.gremlin.server.op.traversal.TraversalOpProcessor, config: { cacheExpirationTime: 600000, cacheMaxSize: 1000 }}
metrics: {
consoleReporter: {enabled: false, interval: 180000},
csvReporter: {enabled: false, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv},
jmxReporter: {enabled: false},
slf4jReporter: {enabled: true, interval: 180000},
gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
graphiteReporter: {enabled: false, interval: 180000}}
threadPoolBoss: 1
maxInitialLineLength: 4096
maxHeaderSize: 8192
maxChunkSize: 8192
maxContentLength: 65536
maxAccumulationBufferComponents: 1024
resultIterationBatchSize: 64
writeBufferHighWaterMark: 32768
writeBufferHighWaterMark: 65536
ssl: {
enabled: false}
ΠΠ½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ "ΠΏΠΎΠ»ΠΎΠΆΠΈΡΡ" BerkeleyDB Π²Π΅ΡΡΠΈΡ JanusGraph.
ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΊΡΠΈΠ²Π°Ρ Π² ΡΠ°ΡΡΠΈ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ², ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΏΡΠΈ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠΈ ΠΈΠ½Π΄Π΅ΠΊΡΠ°ΠΌΠΈ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΡΡΡΠ°Π½Π½ΡΠ΅ ΡΠ°ΠΌΠ°Π½ΡΡΠ²Π° Π½Π° Groovy. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½Π΄Π΅ΠΊΡΠ° Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΡ ΠΊΠΎΠ΄Π° Π² ΠΊΠΎΠ½ΡΠΎΠ»ΠΈ Gremlin (ΠΊΠΎΡΠΎΡΠΎΠ΅, ΠΊΡΡΠ°ΡΠΈ, Π½Π΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΈΠ· ΠΊΠΎΡΠΎΠ±ΠΊΠΈ). ΠΠ· ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΠΎΠΉ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ JanusGraph:
graph.tx().rollback() //Never create new indexes while a transaction is active
mgmt = graph.openManagement()
name = mgmt.getPropertyKey('name')
age = mgmt.getPropertyKey('age')
mgmt.buildIndex('byNameComposite', Vertex.class).addKey(name).buildCompositeIndex()
mgmt.buildIndex('byNameAndAgeComposite', Vertex.class).addKey(name).addKey(age).buildCompositeIndex()
mgmt.commit()
//Wait for the index to become available
ManagementSystem.awaitGraphIndexStatus(graph, 'byNameComposite').call()
ManagementSystem.awaitGraphIndexStatus(graph, 'byNameAndAgeComposite').call()
//Reindex the existing data
mgmt = graph.openManagement()
mgmt.updateIndex(mgmt.getGraphIndex("byNameComposite"), SchemaAction.REINDEX).get()
mgmt.updateIndex(mgmt.getGraphIndex("byNameAndAgeComposite"), SchemaAction.REINDEX).get()
mgmt.commit()
ΠΠΎΡΠ»Π΅ΡΠ»ΠΎΠ²ΠΈΠ΅
Π Π½Π΅ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΠΌΡΡΠ»Π΅ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΠΉ Π²ΡΡΠ΅ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Ρ β ΡΡΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ ΡΠ΅ΠΏΠ»ΠΎΠ³ΠΎ Ρ ΠΌΡΠ³ΠΊΠΈΠΌ. ΠΡΠ»ΠΈ Π²Π΄ΡΠΌΠ°ΡΡΡΡ, ΡΠΎ Π³ΡΠ°ΡΠΎΠ²Π°Ρ Π‘Π£ΠΠ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π΄ΡΡΠ³ΠΈΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΡΠ΅Ρ ΠΆΠ΅ ΡΠ°ΠΌΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ². ΠΠ΄Π½Π°ΠΊΠΎ, Π² ΡΠ°ΠΌΠΊΠ°Ρ ΡΠ΅ΡΡΠΎΠ² Ρ ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΠ» ΠΈ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½Ρ Ρ Π·Π°ΠΏΡΠΎΡΠΎΠΌ Π²ΠΈΠ΄Π°:
g.V().hasLabel('ZoneStep').has('id',0)
.repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',1)).count().next()
ΠΊΠΎΡΠΎΡΡΠΉ ΠΎΡΡΠ°ΠΆΠ°Π΅Ρ ΡΠ°Π³ΠΎΠ²ΡΡ Π΄ΠΎΡΡΡΠΏΠ½ΠΎΡΡΡ. ΠΠ΄Π½Π°ΠΊΠΎ ΠΈ Π½Π° ΡΠ°ΠΊΠΈΡ
Π΄Π°Π½Π½ΡΡ
Π³ΡΠ°ΡΠΎΠ²Π°Ρ Π‘Π£ΠΠ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π»Π° ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΡΡ
ΠΎΠ΄ΠΈΠ» Π·Π° ΠΏΡΠ΅Π΄Π΅Π»Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ
ΡΠ΅ΠΊΡΠ½Π΄β¦ ΠΡΠΎ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ, ΠΆΠ΅ ΡΠ²ΡΠ·Π°Π½ΠΎ Ρ ΡΠ΅ΠΌ, ΡΡΠΎ Π±ΡΠ»ΠΈ ΠΏΡΡΠΈ Π²ΠΈΠ΄Π° 0 -> X -> Y ... -> 1
, ΠΊΠΎΡΠΎΡΡΠ΅ Π³ΡΠ°ΡΠΎΠ²ΡΠΉ Π΄Π²ΠΈΠΆΠΎΠΊ ΡΠΎΠΆΠ΅ ΠΏΡΠΎΠ²Π΅ΡΡΠ».
ΠΠ°ΠΆΠ΅ Π΄Π»Ρ Π·Π°ΠΏΡΠΎΡΠ° Π²ΠΈΠ΄Π°:
g.V().hasLabel('ZoneStep').has('id',0).out().has('id',1)).count().next()
ΠΌΠ½Π΅ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ ΠΏΠΎΠ»ΡΡΠΈΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΡΠΉ ΠΎΡΠ²Π΅Ρ Ρ Π²ΡΠ΅ΠΌΠ΅Π½Π΅ΠΌ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΌΠ΅Π½ΡΡΠ΅ ΡΠ΅ΠΊΡΠ½Π΄Ρ.
ΠΠΎΡΠ°Π»Ρ Π±Π°ΡΠ½ΠΈ ΡΠ°ΠΊΠΎΠ²Π°, ΡΡΠΎ ΠΊΡΠ°ΡΠΈΠ²Π°Ρ ΠΈΠ΄Π΅Ρ ΠΈ ΠΏΠ°ΡΠ°Π΄ΠΈΠ³ΠΌΠ°ΡΠΈΡΠ½ΠΎΠ΅ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π΅ Π²Π΅Π΄ΡΡ ΠΊ ΠΆΠ΅Π»Π°Π΅ΠΌΠΎΠΌΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΡ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΎ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π±ΠΎΠ»Π΅Π΅ Π²ΡΡΠΎΠΊΠΎΠΉ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡΡ Π΄Π΅ΠΌΠΎΠ½ΡΡΡΠΈΡΡΠ΅ΡΡΡ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ ClickHouse. ΠΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΠΉ Π² ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Π²Π°ΡΠΈΠ°Π½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ β ΡΠ²Π½ΡΠΉ Π°Π½ΡΠΈΠΏΠ°ΡΡΠ΅ΡΠ½ Π΄Π»Ρ Π³ΡΠ°ΡΠΎΠ²ΡΡ Π‘Π£ΠΠ, Ρ ΠΎΡΡ ΠΈ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΠΊΠ°ΠΊ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠΈΠΉ Π΄Π»Ρ ΠΌΠΎΠ΄Π΅Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² ΠΈΡ ΠΏΠ°ΡΠ°Π΄ΠΈΠ³ΠΌΠ΅.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com