á¡á¬ážáá¯á¶ážáááºá¹ááá¬áá«á á¡á±á¬á·ááºááá¯ááºážá¡ááœá¬ážá¡áᬠááœá²ááŒááºážá áááºááŒá¬ááŒááºážá¡ááœáẠáá¯ááºáá¯ááºáá áºáá¯ááᯠáá»áœááºá¯ááºááá¯á· áááºáá®ážáá±áá«áááºá ááá±á¬áá»ááºááœáẠáá±áá¡ááŸá¶á· ááá®ážááœá¬ážáááºážááŒá±á¬ááºážáá»á¬ážááᯠá á¬áááºážá¡ááºážááœá²ááŒááºážá áááºááŒá¬ááŒááºážááŸáá·áº áááºááá¯ááºááá·áº áá¬áááºáá áºáᯠááŸááááºá
á€áá¯ááºáááºážáá±á¬ááºáá¬á áá áºá áááºáá áºááá¯ááºážá¡áá±ááŒáá·áºá á¡áá¯á¶ážááŒá¯áá°áá»á¬ážááẠá¡á±á¬ááºáá«á¡áá»áá¯ážá¡á á¬ážá á áá áºáá±ážááœááºážáá»á¬ážááᯠáá±ážááŒááºážááá¯ááºáááº-
- á§áááᬠ"A" á០á§áááᬠ"B" ááá¯á· á§áá·áºááẠáááºáá»áŸ ááŒááºáááºážáá²á·áááºá
- á§áááᬠ"A" á០á§áááᬠ"B" ááá¯á· á§áááᬠ"C" ááŸáááá·áº á§áááᬠ"D" ááá¯á· á§áá·áºáááºáááºáá»áŸ ááŒááºáááºážáá²á·áááºá
- á§áááᬠâAâ á០á§áááᬠâBâ ááá¯á· á§áá·áºáááºá¡áá»áá¯ážá¡á á¬ážáá áºáá¯á¡ááœáẠá¡áá»áááºáááºáá»áŸááŒá¬áááºá
ááŸáá·áº á¡áá¬ážáá° ááœá²ááŒááºážá áááºááŒá¬ááŸá¯ááá¯ááºáᬠáá±ážááœááºážáá»á¬ážá áœá¬á
á§áá·áºáááºáá»á¬ážá ááœá±á·áá»á¬ážááŸá¯ááẠáá±áá¬áá»á¬ážá¡ááŸá¶á· ááœáŸááºááŒáá¬ážáá±á¬ ááááºáá áºáá áºáá¯ááŒá áºáááºá á¡ááºáá¬áááºááá¯áááºááŒá®ážáá±á¬ááºá ááááºáá ẠDBMSs áá»á¬ážááᯠááœá²ááŒááºážá áááºááŒá¬ááŸá¯á¡á á®áááºáá¶á á¬áá»á¬ážá¡ááœááºáááºáž á¡áá¯á¶ážááŒá¯ááŒá±á¬ááºáž ááœá±á·ááŸááá²á·áááºá ááááºáá ẠDBMSs ááẠááá¯ááá¯á·áá±á¬áá±ážááœááºážáá»á¬ážááᯠáááºááá¯á·áááºááá¯ááºááááºááᯠáá»áœááºá¯ááºááŒááºááá¯áá²á·ááẠ(TL; DR; áá¶á·áá»ááºážáááº)á
DBMS ááᯠáá¯á¶ážááá¯á· ááœá±ážáá»ááºáá²á·áááºá
- BerkeleyDB ááá¯ááŸá±á¬ááºááŸá¯áá±á¬ááºááœááºááœááºá Apache Cassandraá Scyllaá
- ááŸá¯ááºááœá±ážáá±á¬á¡ááœáŸááºážáá»á¬ážááᯠLuceneá Elasticsearchá Solr ááœáẠááááºážáááºážááá¯ááºáááºá
JanusGraph áá á¬áá±ážááá¬áá»á¬ážááááºážááẠOLTP ááŸáá·áº OLAP ááŸá áºáá»áá¯ážáá¯á¶ážá¡ááœááºááá·áºáá»á±á¬áºáááºáá¯áá±ážáááºá
BerkeleyDBá Apache Cassandraá Scylla ááŸáá·áº ES ááá¯á·ááŸáá·áº á¡áá¯ááºáá¯ááºáá²á·ááŒá®ážá á€áá¯ááºáá¯ááºáá»á¬ážááᯠáá»áœááºá¯ááºááá¯á·áá áá áºáá»á¬ážááœáẠá¡áá¯á¶ážááŒá¯áá±á·ááŸááá±á¬ááŒá±á¬áá·áº á€ááááºááᯠDBMS á ááºážáááºááŒááºážááŸáá·áºáááºáááºá á¡áá±á¬ááºážááŒááºáááá«áááºá RocksDB ááẠBerkeleyDB ááᯠááœá±ážááᬠáá°ážáááºážáá¬ááœá±á·áá±ááá·áº áá«á ááœá±áá±ážááœá±áá° ááá¯á¡ááºáá»ááºááœá±ááŒá±á¬áá·áº ááŒá áºááá¯ááºáááºá áááºááá¯á·áááºááá¯á á±áá¬áá° á¡ááá¯ááºážá¡áá¬ááŒáá·áº áá¯ááºáá¯ááºá¡áá¯á¶ážááŒá¯ááŸá¯á¡ááœááºá Cassandra ááá¯á·ááá¯áẠScylla ááœáẠáá±á¬ááºáá¶ááá¯ááºááᯠá¡áá¯á¶ážááŒá¯ááẠá¡ááŒá¶ááŒá¯áá¬ážáááºá
á¡á á¯ááá¯ááºááœá²á·ááŒááºážááẠáá¯ááºáá¯ááºááẠopen source ááá¯ááºááá·áºá¡ááœááºááŒá±á¬áá·áº Neo4j ááᯠáá»áœááºá¯ááºáá ááºážá á¬ážáá²á·áá«á
ááááºáá ẠDBMSs áááŒá±á¬áááº- "ááááºáá áºáá¯á¶ááá¹áá¬ááºáá°áá«áá ááááºáá áºáá²á·ááá¯á·áááºáá¶áá«á" - á¡ááŸá¡á!
áááá áá»áœááºá¯ááºááẠááááºáá ẠDBMSs á canons áá»á¬ážááŸáá·áºá¡áá® á¡ááá¡áá»ááŒá¯áá¯ááºáá¬ážááá·áº ááááºáá áºáá¯ááᯠáá±ážááœá²áá²á·áááº-
á¡ááŸá
áºáá¬áááŸááá«áááºá 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()
áá¯ááŸá¬ážáá¬áá¬ááŒáá·áº áá°ááẠá€áá²á·ááá¯á·áá±á¬ á¡áá¬ááŒá áºáááº- ID=0 áá«áá±á¬ áá¯ááºáá áºáá¯ááᯠááŸá¬áá«á áááºážááá¯á·ááœá¬ážááá·áº á¡á áœááºážáá»á¬áž (ZoneStep) á០áá±á«ááºááá¯ááºáá»á¬ážá¡á¬ážáá¯á¶ážááᯠáá°áá«á áá¯ááºááá¯á· á¡á áœááºážáá áºáá¯ááŸáááá·áº áá¯ááºá¡ááá·áºáá»á¬ážááᯠáááºáááœá±á·ááá»ááºáž ááŒááºáááœá¬ážááẠáááºááá·áºáá«á ID=19á ááá¯áá²á·ááá¯á·áá±á¬ ááŒáá¯ážáá»á¬ážááᯠáá±ááœááºáá«á
ááááºáá»á¬ážáá±á«áºááœáẠááŸá¬ááœá±ááŒááºážá ááŸá¯ááºááœá±ážááŸá¯áá»á¬ážá¡á¬ážáá¯á¶ážááᯠáá»áœááºá¯ááºááááááºáá±á¬ááºáá±á¬áºáááºáž á€áá±ážááœááºážááᯠá€á
á¬á¡á¯ááºáá±á«áºááœáẠá¡ááŒá±áá¶á áá¯ááºáá±ážáá²á·ááẠ(
BerkeleyDB áá±á¬ááºáá¶ááá¯á¡áá¯á¶ážááŒá¯á á¡ááœáŸááºážáá»á¬ážáááºáá®ážáá¬ážáá±á¬ JanusGraph ááááºáá
áºáá±áá¬áá±á·á
áºááá¯á· á¡ááŸáẠ50 á០3 ááŸááºá¡ááááŸááá±á¬ á¡áá¯ááºáá± 20 ááᯠáááºáá±ážááá¯ááºáá«áááºá
Python áá±á«ááºážáá¯áẠscript-
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)
SSD ááœáẠ4 cores ááŸáá·áº 16 GB RAM áá«áá±á¬ VM ááᯠá¡áá¯á¶ážááŒá¯áá¬ážáááºá JanusGraph ááẠá€á¡áááá·áºááᯠá¡áá¯á¶ážááŒá¯á á¡áá¯á¶ážááŒá¯áá¬ážáááºá
docker run --name janusgraph -p8182:8182 janusgraph/janusgraph:latest
á€ááá á¹á ááœááºá á¡ááá¡áá»ááá¯ááºáá®ááŸá¯ááŸá¬ááœá±ááŸá¯áá»á¬ážá¡ááœááºá¡áá¯á¶ážááŒá¯ááá·áºáá±áá¬ááŸáá·áºá¡ááœáŸááºážáá»á¬ážááᯠBerkeleyDB ááœááºááááºážáááºážáá¬ážáááºá á á±á¬á á±á¬ááá±ážáá²á·áá²á· áá±á¬ááºážááá¯áá»ááºááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºááŒá®ážááẠá áá¹ááá·áºáááºááááºážáá²á· áá®áá»áŸáá²á· á¡áá»áááºááᯠááá²á·áá«áááºá
á¡áááºáá±á¬áºááŒáá« script 4 áá¯ááᯠá¡ááŒáá¯ááºáá¯ááºáá±á¬ááºááŒááºážááŒáá·áº Docker ááŸááºáááºážáá»á¬ážááœáẠáá»á±á¬áºááœáŸááºá áá¬áá±á¬ááºážáá±á¬ Java stacktraces áá»á¬ážááŸáá·áºá¡áá° DBMS ááᯠááœáŸá±ááá¯á¶áá®ážá¡ááŒá áºááá¯á· ááŒá±á¬ááºážáá²ááá¯ááºáá²á·áááºá
á ááºážá á¬ážááŒá®ážáá±á¬ááºá áá»áœááºá¯ááºááẠááááºááá¬ážááᯠá¡á±á¬ááºáá«á¡ááá¯ááºážááá¯ážááŸááºážá¡á±á¬ááºááŒá¯áá¯ááºááẠáá¯á¶ážááŒááºáá²á·áááº-
á¡á áœááºážáá»á¬ážááŒáá·áº ááŸá¬ááœá±ááŒááºážááẠentity attribute áá»á¬ážááŒáá·áº ááŸá¬ááœá±ááŒááºážááẠááá¯ááŒááºáááºáᯠáá¯á¶ážááŒááºááŒááºážá ááá¯á·ááŒá±á¬áá·áºá áá»áœááºá¯ááºá áá±á¬ááºážááá¯áá»ááºááẠá¡á±á¬ááºáá«á¡ááá¯ááºáž ááŒá áºááœá¬ážáááº-
g.V().hasLabel('ZoneStep').has('id',0).repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',19)).count().next()
áá¯ááŸáá¬áá¬ááŒáá·áº áá°ááẠá€áá²á·ááá¯á·áá±á¬ á¡áá¬ááŒá áºáááº- ID=0 ááŒáá·áº ZoneStep ááá¯ááŸá¬áá«á ZoneStep ááᯠID=19 ááŒáá·áºááŸá¬áááœá±á·ááá»ááºáž áá±á¬ááºááŒááºááá¯ááºáá² áááºááá·áºáá«á ááá¯áá²á·ááá¯á·áá±á¬ ááœááºážáááºá¡áá±á¡ááœááºááᯠáá±ááœááºáá«á
áááá¯á¡ááºáá±á¬ áá»áááºáááºááŸá¯áá»á¬áž ááááºáá®ážááá¯ááºá á±áááºá áááºááœáŸááºážáá»ááºáá»á¬ážááœáẠááááááá¯ááºááᯠááá·áºáááºáá¬ážááŒááºáž áááŸáá á±ááááºá¡ááœáẠá¡áááºááœáẠáá±á¬áºááŒáá¬ážáá±á¬ áááºááŒááºáž script ááᯠááá¯ážááŸááºážá¡á±á¬áẠááŒá¯áá¯ááºáá¬ážáá«áááºá
AdHoc áá±á¬ááºážááá¯ááŸá¯áá»á¬ážá áááºááœááºáá»ááºáá»á¬ážá¡ááœáẠáá¯á¶ážá áááá·áºáá»á±á¬áºáá±á¬ááŒá±á¬áá·áº áá±á¬ááºážááá¯áá»ááºááẠááŒá®ážááŒá±á¬ááºááẠá áá¹ááá·áºáá»á¬ážá áœá¬ á¡áá»áááºáá°ááá±ážáááºá
áá« JanusGraph ááᯠá¡ááŒááºáá¯á¶áž Cassandra á¡áá±á¬ááºá¡áááºáá±á¬áºááŸá¯á¡ááŒá ẠScylla ááá¯á¡áá¯á¶ážááŒá¯á á¡áá¯á¶ážááŒá¯ááẠááŒáá¯ážá á¬ážáá²á·áá±á¬áºáááºážá áááºážááẠáááá¬áááºááŸá¬ážáá±á¬ á áœááºážáá±á¬ááºáááºááŒá±á¬ááºážáá²ááŸá¯áá»á¬ážááᯠáááŒá áºáá±á«áºá á±áá²á·áá«á
ááá¯á·ááŒá±á¬áá·áº "ááááºáá¯á¶áá¯á¶ááá¹áá¬ááº" ááŒá áºáá±ááá·áºáá á¬áž ááááºáá ẠDBMS ááẠáááºážááᯠáá»ááºááŒááºá áœá¬ áá¯ááºáá±á¬ááºááẠááááá¯ááºáá«á áá«ááááá±á¬á¡áá¬áá áºáá¯ááŸááááºááŸáá·áº JanusGraph áááºá€ááŸá¬ááœá±ááŸá¯ááá¯á áá¹ááá·áºá¡áááºážáááºá¡ááœááºážáá¯ááºáá±á¬ááºáááºááŒá¯áá¯ááºááá¯ááºáááºáá¯á¡ááŒáá·áºá¡ááá°ááá±á¬áºáááºážá áá«ááá¯ááºáá±á¬ááºááá¯ááºáá²á·áá«á
ááŒá¿áá¬ááᯠááŒá±ááŸááºážááẠááá¯á¡ááºáá±áá±ážáá±á¬ááŒá±á¬áá·áºá áá»ááºááá±ááŸáááŸá á¡áá±á¬ááºážááŒááºáá«áááᯠáááŸá¯á¶á·áá±á¬áºáá²á áááºááœá±á·ááœáẠáá¯á¶ážááá¯ááºáá±á¬ááºááá¯ááºáá±á¬ ááœá±ážáá»ááºááŸá¯áá áºáᯠááŒá áºááá¯ááºáááºá
áá»áœááºá¯ááºááá¯á·áááá±á¬áá»ááºááẠApache ClickHouse ááá¯á¡áá¯á¶ážááŒá¯áá¬ážááŒá®ážááŒá áºáá±á¬ááŒá±á¬áá·áº á€ááœá²ááŒááºážá áááºááŒá¬ááŸá¯ DBMS ááœáẠáá»áœááºá¯ááºááá¯áá±ááááᯠá ááºážáááºááẠáá¯á¶ážááŒááºáá²á·áááºá
ááá¯ážááŸááºážáá±á¬ áá»ááºááŒá¯ááºáááºážááᯠá¡áá¯á¶ážááŒá¯á 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
á¡á±á¬ááºáá±á¬áºááŒáá« script ááá¯á¡áá¯á¶ážááŒá¯á áááºážááᯠáá±áá¬áá»á¬ážááŒáá·áº ááŒáá·áºááœááºážáá²á·áá«áááºá
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 á០á¡ááŸáẠB ááá¯á· ááœáŸá±á·áááº-
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
áá±á¬ááºážááá¯áá»ááºáá»á¬ážááẠá¡ááŸááºááááºááẠááŒá±á¬ááºá áá¬áá±á¬ááºážáááº; á¡ááŸááºááááºá¡áá¯á¶ážááŒá¯áááºá¡ááœááºá áááºááẠsoftware generator ááŒáá¯ážááŒáá¯ážááá¯áááºáá®ážááẠááá¯á¡ááºáá«áááºá ááá¯á·áá±á¬áº áá°ááá¯á·ááẠá¡áá¯ááºáá¯ááºááŒááŒá®áž áá»ááºááŒááºá áœá¬ á¡áá¯ááºáá¯ááºááŒáááºá ááá ááŸáá·áº áá¯ááá áá±á¬ááºážááá¯áá»áẠááŸá áºáá¯á áá¯á¶ážááẠ0.1 á áá¹ááá·áºáááºáááºážá ááŒá®ážááŒá±á¬ááºáá«áááºá á€áááºááŸá¬ á¡áá»áẠ3 áá¯ááá¯ááŒááºáááºážááœá¬ážáá±á¬ count(*) á¡ááœáẠquery execution time á á¥ááá¬áá áºáá¯ááŒá áºáááºá
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 ááẠdisk subsystem ááœááºá¡áááºážáá¯á¶ážáááºááá¯áá¯ááºáá±ážáááºá
áá±á¬ááºáá»ááº
á€áá±á¬ááºážááá¯ááŸá¯á¡áá»áá¯ážá¡á á¬ážááᯠáááºáá±á¬ááºááŸá¯áá±ážááẠClickHouse ááᯠá¡áá¯á¶ážááŒá¯ááẠáá¯á¶ážááŒááºáá²á·áááºá ClickHouse áá²ááá¯á·áááá·áºáá® Apache Flink ááá¯á¡áá¯á¶ážááŒá¯á á¡á á®á¡á ááºá á®ážááŒá±á¬ááºážááá¯ááŒáá¯áááºáá¯ááºáá±á¬ááºááŒááºážááŒáá·áº áá¯ááºáá¯á¶ážáá±á«áºáá±á¬á¡ááŒááºáá»á¬ážááŸáá·áº á¡ááŒáá¯ááºááŒá¯áá¯ááºááŒááºážáá»á¬ážááá¯á¡áá¯á¶ážááŒá¯á áá±ážááœááºážáá»á¬ážááᯠá¡ááŒá²áááºážááá¯áá±á¬ááºážá¡á±á¬ááºááŒá¯áá¯ááºááá¯ááºáá«áááºá
á áœááºážáá±á¬ááºáááºááẠá¡ááœááºáá±á¬ááºážááœááºáá±á¬ááŒá±á¬áá·áº pivoting tables ááᯠáááá¯ááááºáá»áá» á ááºážá á¬ážáááºááẠáááá¯á¡ááºáá±á ááááºáá áá»áœááºá¯ááºááá¯á·ááẠApache Parquet ááá¯á· á¡ááºáá¯ááºáááºááŒááºážááŒáá·áº Vertica á០ááŒááºáááºááá°ááá·áº áá±áᬠpivots áá»á¬ážááᯠáá¯ááºáá±á¬ááºáá²á·ááááºá
áá¶ááá±á¬ááºážá áœá¬ááŒáá·áºá áááẠDBMS ááá¯á¡áá¯á¶ážááŒá¯ááẠáá±á¬ááºáááºááŒáá¯ážá á¬ážááŸá¯ áá¡á±á¬ááºááŒááºáá²á·áá«á áá¯ááºáá¯ááºááᯠá¡ááŸáááºááŒáŸáá·áºááẠááœááºáá°á á±ááá·áº áá±á¬áºááœá±áá±á¬ áá±áá áá áºáá áºáá¯ááŸáááẠJanusGraph áááœá±á·áá«á áá áºáá»áááºáááºážááŸá¬áááºá áá¬áá¬ááᯠconfigure áá¯ááºáááºá Java ááŸáá·áº ááááºážááŸá®ážáá±á¬áá°áá»á¬áž ááœá±ážáá»ááºáááºáá»á á±ááá·áº ááá¯ážáᬠ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}
JanusGraph á BerkeleyDB áá¬ážááŸááºážááᯠááá±á¬áºáá "ááœááºáž" ááá¯ááºáá²á·áááºá
á¡ááœáŸááºážáá»á¬ážááᯠá á®áá¶ááá·áºááœá²áá¬ááœáẠáááºááẠGroovy ááœáẠá¡ááœááºáá°ážáááºážáá±á¬ shamanism á¡áá»áá¯á·ááᯠáá¯ááºáá±á¬ááºááẠááá¯á¡ááºáá±á¬ááŒá±á¬áá·áº á á¬ááœááºá á¬áááºážáá»á¬ážááẠá¡ááœáŸááºážááááºážáá»á¬ážááŸáá·áº áááºáááºá á¡áá±á¬áºáá±áž ááœá²áá±áá«áááºá á¥ááá¬á¡á¬ážááŒáá·áºá á¡ááœáŸááºážáá áºáá¯áááºáá®ážááŒááºážááᯠ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()
afterword
áá áºáááºážá¡á¬ážááŒáá·áº á¡áááºáá±á¬áºááŒáá« á ááºážáááºáá»ááºááẠááœá±ážááœá±ážááŸá¯ááŸáá·áº áá»á±á¬á·áá»á±á¬ááºážááŸá¯ááá¯á·ááŒá¬áž ááŸáá¯ááºážááŸááºáá»ááºááŒá áºáááºá áááºážááᯠáááºá ááºážá á¬ážáá«áá áááẠDBMS ááẠáá°áá®áá±á¬ááááºáá»á¬ážáááŸáááẠá¡ááŒá¬ážáá¯ááºáá±á¬ááºááŸá¯áá»á¬ážááᯠáá¯ááºáá±á¬ááºáááºá ááá¯á·áá±á¬áºáááºáž á ááºážáááºááŸá¯á áá áºá áááºáá áºááá¯ááºážá¡áá±ááŒáá·áºá áá»áœááºá¯ááºááẠá¡á±á¬ááºáá«áá²á·ááá¯á·áá±á¬ áá±á¬ááºážááá¯áá»ááºáá áºáá¯ááŒáá·áº á ááºážáááºááŸá¯áá áºáá¯ááá¯áááºáž ááŒá¯áá¯ááºáá²á·áá«áááºá
g.V().hasLabel('ZoneStep').has('id',0)
.repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',1)).count().next()
áááºážáá»áŸá±á¬ááºá¡ááœá¬á¡áá±ážááᯠáá±á¬ááºááŒááºáááºáááºá ááá¯á·áá±á¬áºá ááá¯áá²á·ááá¯á·áá±á¬áá±áá¬ááœááºáááºá áááẠDBMS ááẠá
áá¹ááá·áºá¡áááºážáááºáá»á±á¬áºááœááºááœá¬ážáá±á¬ááááºáá»á¬ážááá¯ááŒááá²á·áááº... á€áááºááŸá¬ áááºážááŒá±á¬ááºážáá²á·ááá¯á·áá±á¬áááºážááŒá±á¬ááºážáá»á¬ážááŸááá±ááŒááºážááŒá±á¬áá·áºááŒá
áºáááºá 0 -> X -> Y ... -> 1
ááááºáá
áºá¡ááºáá»ááºááá¯áááºáž á
á
áºáá±ážáá±ážáá±á¬á
áá²á·ááá¯á·áá±á¬áá±ážááŒááºážááŸá¯á¡ááœááºáááº
g.V().hasLabel('ZoneStep').has('id',0).out().has('id',1)).count().next()
áá áºá áá¹ááá·áºáááºáááºážáá±á¬ áá¯ááºáá±á¬ááºáá»áááºááŒáá·áº ááŒá áºááœááºážáá±á¬ áá¯á¶á·ááŒááºááŸá¯ááᯠáá»áœááºá¯ááºááááá¯ááºáá«á
áá¬ááºáááºážáááá¯ááºáá»áá·áºááá¬ážááŸá¬ ááŸááá±á¬á áááºáá°ážááŸáá·áº á á¶ááŒáá¯á¶á á¶áá áºáá¯ááẠClickHouse áááá°áá¬ááá¯á¡áá¯á¶ážááŒá¯á ááá¯ááá¯ááŒáá·áºáá¬ážáá±á¬áááá±á¬ááºááŸá¯ááŒáá·áºááŒááá¬ážááá·áºá¡ááá¯ááŸááá±á¬ááááºááá¯á·áááá¯á·áá±á¬ááºááá¯ááºááŒááºážááŒá±á¬áá·áºááŒá áºáááºá á€áá±á¬ááºážáá«ážááœááºáááºááŒáá¬ážáá±á¬á¡áá¯á¶ážááŒá¯ááŸá¯ááá á¹á ááẠáááẠDBMSs á¡ááœááºááŸááºážáááºážááŒááºáá¬ážáá±á¬áá¯á¶á á¶ááŒá áºáááºá ááá¯á·áá±á¬áºáááºážáááºáááºážááá¯á·ááá«áá¬ááá¯ááºážááœááºáá¯á¶á á¶ááŒáááºá¡ááœááºááá·áºáá»á±á¬áºáá¯á¶ááááºá
source: www.habr.com