αα½ααααΈβα’αααβααΆααα’ααααααΆα ααΎααααα»ααααααΎαααα·ααααααααΆααααΆααα·ααΆαα ααΆα ααααααα αααααΆαα αααααααααααΆαααΆααα·α αα ααΆααααααΉαααΆααα·ααΆααααα·αα·ααααααΌαα’αααααααααΆαα ααΌααΆαααααααα
ααΆααααααααα·α αα ααΆαααα α’αααααααΎααααΆααα’αΆα αα½ααααα½αααααααααααααααααααΆααααααα
- ααΎααΆαααα»αααααα»ααααΆαααΆααααΆαααααααΆααααΈααααα "A" αα ααααα "B";
- ααΎααΆαααα»αααααα»ααααΆαααΆααααΆαααααααΆααααααα "A" αα ααααα "B" ααΆααααααααα "C" α αΎααααααΆααααααααααΆααααααα "D";
- ααΎααααΌαα αααΆααααααα»ααααΆααααααΆααααααααααα αααααααααΆααααΆαααα½ααααα»αααΆαααααΎααααΎαααΈααααα "A" αα ααααα "B" α
αα·ααααα½ααα·ααΆαααααααααααΆαα½αα ααα½αα
α αααΆααααα’αααααααααΆαα ααΌααΆαααααααααΊααΆααααΆα ααααΉαααΆαα αααααΆααααΈα’αΆαα’ααΈαααΊαα·α αααα»αααΆαααααΎαααΆααααΆα αα DBMS ααααΌαααΆαααααΎαααααΆαααααΆαααΆααααα·ααΆααααααα αααα»αααΆαααααααααΆααααΆα ααααΎαααΈαααααααααααΆα αα DBMSs ααΉααααααααΆαααΆαα½αααΉααααα½ααααααα (TL; DR; αα·αααα’) α
αααα»αααΆαααααΎαααΎαααααΎ DBMS
- αααααααΆαααααααααα»α BerkeleyDB, Apache Cassandra, Scylla;
- ααααααααααααα»αααααΆαα’αΆα ααααΌαααΆααααααΆαα»ααα αααα»α Lucene, Elasticsearch, Solr α
α’ααααα·αααααα JanusGraph αααααααΆααΆαααααααααααΆααααΆαα OLTP αα·α OLAP α
αααα»αααΆαααααΎααΆαααΆαα½α BerkeleyDB, Apache Cassandra, Scylla αα·α ES α αΎαααα·αααααΆαααααααααΌαααΆαααααΎααααΆααααΆααΉαααΆαααα αααα»αααααααααααααααΎα ααΌα αααααααα»αααΆααα»αα·αααα·αα·ααα ααααααΆαααΆαααααααααΆα αα DBMS αααα αααα»αααΆαααααΎαααΆααΆααΆααΏαα ααααααααα»αααΆαααααΎαααΎα BerkeleyDB ααΎ RocksDB ααα»ααααααααααα ααααΆαααααΆααααααααΌαααΆαααααα·ααααα·ααΆαα αααα»αααααΈααΆααααα αααααΆααααΆαααααΎααΆαααααααΆα ααΆαααααΎααααΆααααα·ααα ααΆααααΌαααΆαααααΎα±ααααααΎαααααααΆαααααααα ααΎ Cassandra α¬ Scylla α
αααα»ααα·αααΆααα·α αΆαααΆ Neo4j αα ααΈαααααααΆαααΆααα ααααααααααΌαα±ααααΆαααααααΆαα·ααααααα αααααΊααα·ααααα·ααααααΆαααααααΎαα αα ααα
ααααΆα αα DBMSs αα·ααΆαααΆ "ααααα·αααΎααΆααΎααα ααΌα ααΆααααΆα αα α αΌαα αΆαααα»αααΆααΌα ααΆααααΆα αα!" - αααααα!
ααααΌαβαααα»αβααΌαβααααΆα ααβαααβααααΌαβααΆαβααααΎβα‘αΎαβαααΆαβαα·αβααααΆααβαααβαααβααΆα Canons ααβααααΆα αα DBMSα
ααΆαααααΉαααΆααα½αα 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()
α’αααΈαααααΆααΆααΆαα»ααααΈααΊααΌα αααα αααααααααααααααααΆαααααααααΆαα = 0 ααα ααα»α ααααΌαααΆααα’αααααααααα½ααα ααΆ (ZoneStep) αααααααα·αααααααααααααα αΌααααα’αααααααΎα ZoneSteps ααΆααααααααααΆαααααα αααααααΆαα½α 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 αααααΆα 4 cores αα·α 16 GB RAM αα ααΎ SSD α JanusGraph ααααΌαααΆαααΆαααααααΆααααααααΎααΆααααααααΆαααα
docker run --name janusgraph -p8182:8182 janusgraph/janusgraph:latest
αααα»αααααΈααα αα·αααααα αα·ααα·αα·αααααααααααΌαααΆαααααΎαααααΆααααΆααααααααααΆαααααΌαααααα·αααααΆααααααΌαααΆααααααΆαα»ααα αααα»α BerkeleyDB α αααβααΆαβα’αα»ααααβααααΎβαααβααΆαβαααααβα±ααβαα»αβααα αααα»αβααΆαβααα½αβαααβααααΆβααααΎβααΉαβααΆααβαα·αβαα·ααΆααΈα
αααααααΎαααΆαααααααΈαααΆαα 4 ααΆαααΎααααααααΆ αααα»αααΆααααααααααααΎααααΈααααααααΆα DBMS αα ααΆαααα ααΆαα½αααΉαααααααΈα Java stacktraces ααααΈαααΆα (α αΎαααΎαααΆααα’ααααααΆα αΌαα α·αααα’αΆα Java stacktraces) αα αααα»ααααααα ααα» Docker α
αααααΆααβααΈβααΆαβαα·αβαα½αβα ααα½α αααα»αβααΆαβαααααα βα α·αααβααααα½αβααααΆααααΆαβααααΆα ααβαα βααΌα βααΆαβαααααα
ααΆααααααα ααΆααΆααααααααααΆααα»αααααααα’αααααΆαααΉαααΏαααΆαααΆααααααααααΆααααα ααΆαααααα ααααΎαααααααα»αααΆααααααα ααΆααΌα ααΆααααααα
g.V().hasLabel('ZoneStep').has('id',0).repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',19)).count().next()
α’αααΈαααααΆααΆααΆαα»ααααΈααΆαα’αααΈαα½αααΌα αααα ααααααα ZoneStep ααΆαα½α ID=0, stomp ααααα·αααααααααααααα αΌααααα’αααααααΎα ZoneStep ααΆαα½α ID=19, ααΆααα ααα½αα αααααΆααααααααα
αααα»αααααΆαααααα½αααΆααααα»αααααααΈααααααΆααααααα±ααααΆαααΎ ααΎααααΈαα»αα±αααααααΎαααΆααααααΆααααααα·αα αΆαααΆα α αααααΆααααααα·ααααα½ααααα»αα αααααα»αααααααα
ααααΎαα ααα αααΆααααααα»ααααΆααα·ααΆααΈααΎααααΈαααα αα αααααΆααΆααα·αα’αΆα ααα½αααααΆαααΆαααααα»ααααααΆαααα·α αα ααΆαααααααΎα αααααααΆαα·αααααααααΉααααααααααααααΎαααα AdHoc αααααααααααα
αααα»αααΆαααααΆααΆαααΆαααααααΆα JanusGraph αααααααΎ Scylla ααΆααΆαα’αα»αααα Cassandra ααΏααααα»α ααα»ααααααααααα·αααΆαα±ααααΆαααΆαααααΆααααααΌαααααΎαααΆαααααΆαααααΆαα½ααααα
ααΌα ααααααΎαααααΈααΆααΆααα·ααααααΆ "ααΆααΎααα ααΌα ααΆααααΆα αα" αααα»ααα·αα’αΆα ααααααΆα αα DBMS ααΎααααΈααααΎαααΆαααΆααΆαααΏαααα αααα»ααααααααααΆαααααααααΆααΆαα’αααΈαα½αααααααα»ααα·αααΉα α αΎαααΆ JanusGraph α’αΆα ααααΌαααΆαααααΎα‘αΎαααΎααααΈααααΎααΆααααααααααααααα»ααααααααα½ααα·ααΆααΈ ααα»αααααααα»ααα·αα’αΆα ααααΎααΆααΆαααα
αααααΆααααα αΆαα ααααααΌααααααααΆα αααα»αα αΆααααααΎααα·αα’αααΈ JOINs αα·α Pivots of tables ααααα·αααΆααααα»αα±ααααΆααα»αα·αααα·αα·ααααΆααααααΉαααΆαααΎαααΆα ααα»ααααα’αΆα ααΆαααααΎααααα’αΆα ααααΎαααΆαααΆαααΆαααααα»ααααα»αααΆαα’αα»ααααα
ααααααααααααΎαααααΎ 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
αααα»αααΆααααααΎα Database αα·αααΆααΆααα½ααα αααα»αααΆααΌα αααα
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 αα α ααα»α 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
ααΎααααΈααααααΆαα α£ αα·αααα»α
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 αα·ααΆααΈα αααααΊααΆα§ααΆα ααααααααααααΆααααα·ααααα·αααα½ααααααΆααααΆαααΆαα (*) ααααααΆαα 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 α
ααΆαααααααααΊααα’ααααΆααααΆαα αααααΎααααα ααααΆαα·αα αΆαααΆα ααα·αα’αααΈααΆααΆα pivoting ααΆααααααα·ααΈαααααα ααΈαα»α ααΎαααααΌαααααΎ pivots αααα·αααααααααααΆαααααΈ Vertica ααΆααααααΆααααα αααα ααΆαα Apache Parquetα
ααΆα’αα»αα ααΆαααα»αααααα½αααααααααααΎααααΈααααΎααααΆα αα DBMS αα·αααααααααα αααα»ααα·αααΆαααααΎαααΆ JanusGraph ααΆαααααααααα’αααΌα‘αΌαααΈαααααΆααααα½αααααΎαααα»αααΆααααααΎαααααΏαααΆαα½αααΉαααα·ααααααααα αααα»ααααααΆαα½αααααΆααα ααΎααααΈααααααα ααΆαααααααααααΆαααΈααα αα·ααΈααΆααααα 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}
αααα»αααΆαααααααααααααα ααααα "ααΆαα" αααα BerkeleyDB αα JanusGraph α
α―αααΆαααΊααΆαααΆαα ααααΌαα ααααααααα»ααααααααααααα·αα·αααα α αΆααααΆααααΈααΆαααααααααααα·αα·αααααααααΌαα±ααα’αααα’αα»αααα shamanism α ααααααα½αα ααα½ααα αααα»α 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()
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 αααααΈααΆααΆα αΆααααΌα ααΆαααααααααααΆααααααΌαα αααα»αααααΌαααααα½ααααααααα
ααααα: www.habr.com