ืึทืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ื˜ืขืกื˜ื™ื ื’ ื“ื™ ืึธื ื•ื•ืขื ื“ืœืขืš ืคื•ืŸ ื“ื™ JanusGraph ื’ืจืึทืคื™ืง DBMS ืคึฟืึทืจ ืกืึทืœื•ื•ื™ื ื’ ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ื“ืขืจื’ื™ื™ื•ื ื’ ืคึผืึทืกื™ืง ืคึผืึทื˜ืก

ืึทืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ื˜ืขืกื˜ื™ื ื’ ื“ื™ ืึธื ื•ื•ืขื ื“ืœืขืš ืคื•ืŸ ื“ื™ JanusGraph ื’ืจืึทืคื™ืง DBMS ืคึฟืึทืจ ืกืึทืœื•ื•ื™ื ื’ ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ื“ืขืจื’ื™ื™ื•ื ื’ ืคึผืึทืกื™ืง ืคึผืึทื˜ืก

ื ื’ื•ื˜ืŸ ื™ืขื“ืขืจ. ืžื™ืจ ืึทื ื˜ื•ื•ื™ืงืœืขืŸ ืึท ืคึผืจืึธื“ื•ืงื˜ ืคึฟืึทืจ ืึธืคืคืœื™ื ืข ืคืึทืจืงืขืจ ืึทื ืึทืœื™ืกื™ืก. ื“ื™ ืคึผืจื•ื™ืขืงื˜ ื”ืื˜ ืึท ืึทืจื‘ืขื˜ ืฉื™ื™ึทื›ื•ืช ืฆื• ืกื˜ืึทื˜ื™ืกื˜ื™ืฉ ืึทื ืึทืœื™ืกื™ืก ืคื•ืŸ ื’ืึทืกื˜ ืจื•ืฅ ืึทืจื™ื‘ืขืจ ืžืงื•ืžื•ืช.

ื•ื•ื™ ืึท ื˜ื™ื™ืœ ืคื•ืŸ ื“ืขื ืึทืจื‘ืขื˜, ื™ื•ื–ืขืจื– ืงืขื ืขืŸ ืคืจืขื’ืŸ ื“ื™ ืกื™ืกื˜ืขื ืงื•ื•ื™ืจื™ื– ืคื•ืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ื˜ื™ืคึผ:

  • ื•ื•ื™ืคื™ืœ ื‘ืื–ื•ื›ืขืจ ื–ืขื ืขืŸ ื“ื•ืจื›ื’ืขื’ืื ื’ืขืŸ ืคื•ืŸ ื’ืขื’ื ื˜ "ื" ืฆื• ื’ืขื’ื ื˜ "ื‘";
  • ื•ื•ื™ืคื™ืœ ื‘ืื–ื•ื›ืขืจ ื–ืขื ืขืŸ ื“ื•ืจื›ื’ืขื’ืื ื’ืขืŸ ืคื•ืŸ ื’ืขื’ื ื˜ "ื" ืฆื• ื’ืขื’ื ื˜ "ื‘" ื“ื•ืจืš ื’ืขื’ื ื˜ "C" ืื•ืŸ ื“ืขืจื ืึธืš ื“ื•ืจืš ื’ืขื’ื ื˜ "ื“";
  • ื•ื•ื™ ืœืึทื ื’ ืขืก ื”ืึธื˜ ื’ืขื“ื•ื™ืขืจื˜ ืคึฟืึทืจ ืึท ื–ื™ื›ืขืจ ื˜ื™ืคึผ ืคื•ืŸ ื’ืึทืกื˜ ืฆื• ืึทืจื•ืžืคืึธืจืŸ ืคื•ืŸ ื’ืขื’ื ื˜ "ื" ืฆื• ื’ืขื’ื ื˜ "ื‘".

ืื•ืŸ ืึท ื ื•ืžืขืจ ืคื•ืŸ ืขื ืœืขืš ืึทื ืึทืœื™ื˜ื™ืงืึทืœ ืคึฟืจืื’ืŸ.

ื“ื™ ื‘ืึทื•ื•ืขื’ื•ื ื’ ืคื•ืŸ ื“ื™ ื’ืึทืกื˜ ืึทืจื™ื‘ืขืจ ื’ืขื‘ื™ื˜ืŸ ืื™ื– ืึท ื“ื™ืจืขืงื˜ืขื“ ื’ืจืึทืคื™ืง. ื ืึธืš ืœื™ื™ืขื ืขืŸ ื“ื™ ืื™ื ื˜ืขืจื ืขื˜, ืื™ืš ื“ื™ืกืงืึทื•ื•ืขืจื“ ืึทื– ื’ืจืึทืคื™ืง ื“ื‘ืžืก ื–ืขื ืขืŸ ืื•ื™ืš ื’ืขื ื™ืฆื˜ ืคึฟืึทืจ ืึทื ืึทืœื™ื˜ื™ืงืึทืœ ืจื™ืคึผืึธืจืฅ. ืื™ืš ื”ืึธื‘ ื’ืขื”ืื˜ ืึท ืคืึทืจืœืึทื ื’ ืฆื• ื–ืขืŸ ื•ื•ื™ ื’ืจืึทืคื™ืง ื“ื‘ืžืก ื•ื•ืึธืœื˜ ืงืึธืคึผืข ืžื™ื˜ ืึทื–ืึท ืคึฟืจืื’ืŸ (ื˜ืœ; ื“ืจ; ืฉืœืขื›ื˜).

ืื™ืš ืื•ื™ืกื“ืขืจื•ื•ื™ื™ืœื˜ ืฆื• ื ื•ืฆืŸ ื“ื™ DBMS JanusGraph, ื•ื•ื™ ืึท ื‘ื•ื™ืœืขื˜ ืคืืจืฉื˜ื™ื™ืขืจ ืคื•ืŸ ื’ืจืึทืคื™ืง ืึธืคึฟืŸ-ืžืงื•ืจ DBMS, ื•ื•ืึธืก ืจื™ืœื™ื™ื– ืื•ื™ืฃ ืึท ืึธื ืœื™ื™ื’ืŸ ืคื•ืŸ ื“ืขืจื•ื•ืึทืงืกืŸ ื˜ืขืงื ืึทืœืึทื“ื–ืฉื™ื–, ื•ื•ืึธืก (ืื™ืŸ ืžื™ื™ืŸ ืžื™ื™ื ื•ื ื’) ื–ืึธืœ ืฆื•ืฉื˜ืขืœืŸ ืขืก ืžื™ื˜ ืœื™ื™ึทื˜ื™ืฉ ืึทืคึผืขืจื™ื™ืฉืึทื ืึทืœ ืงืขืจืึทืงื˜ืขืจื™ืกื˜ื™ืงืก:

  • BerkeleyDB ืกื˜ืึธืจื™ื“ื–ืฉ ื‘ืึทืงืขื ื“, Apache Cassandra, Scylla;
  • ืงืึธืžืคึผืœืขืงืก ื™ื ื“ืขืงืกื™ื– ืงืขื ืขืŸ ื–ื™ื™ืŸ ืกื˜ืึธืจื“ ืื™ืŸ Lucene, Elasticsearch, Solr.

ื“ื™ ืžื—ื‘ืจื™ื ืคื•ืŸ JanusGraph ืฉืจื™ื™ึทื‘ืŸ ืึทื– ืขืก ืื™ื– ืคึผืึทืกื™ืง ืคึฟืึทืจ ื‘ื™ื™ื“ืข OLTP ืื•ืŸ OLAP.

ืื™ืš ื”ืึธื‘ ื’ืขืืจื‘ืขื˜ ืžื™ื˜ BerkeleyDB, Apache Cassandra, Scylla ืื•ืŸ ES, ืื•ืŸ ื“ื™ ืคึผืจืึธื“ื•ืงื˜ืŸ ื–ืขื ืขืŸ ืึธืคื˜ ื’ืขื ื™ืฆื˜ ืื™ืŸ ืื•ื ื“ื–ืขืจ ืกื™ืกื˜ืขืžืขืŸ, ืึทื–ื•ื™ ืื™ืš ืื™ื– ื’ืขื•ื•ืขืŸ ืึธืคึผื˜ื™ืžื™ืกื˜ื™ืฉ ื•ื•ืขื’ืŸ ื˜ืขืกื˜ื™ื ื’ ื“ืขื ื’ืจืึทืคื™ืง DBMS. ืื™ืš ื’ืขืคึฟื•ื ืขืŸ ืขืก ืžืึธื“ื ืข ืฆื• ืงืœื™ื™ึทื‘ืŸ BerkeleyDB ืื™ื‘ืขืจ RocksDB, ืึธื‘ืขืจ ื“ืึธืก ืื™ื– ืžื™ืกื˜ืึธืžืข ืจืขื›ื˜ ืฆื• ื“ืขืจ ื˜ืจืึทื ืกืึทืงื˜ื™ืึธืŸ ืจืขืงื•ื•ื™ืจืขืžืขื ืฅ. ืื™ืŸ ืงื™ื™ืŸ ืคืึทืœ, ืคึฟืึทืจ ืกืงืึทืœืึทื‘ืœืข ืคึผืจืึธื“ื•ืงื˜ ื ื•ืฆืŸ, ืขืก ืื™ื– ืกืึทื’ื“ื–ืฉืขืกื˜ื™ื“ ืฆื• ื ื•ืฆืŸ ืึท ื‘ืึทืงืขื ื“ ืื•ื™ืฃ Cassandra ืึธื“ืขืจ Scylla.

ืื™ืš ื”ืึธื‘ ื ื™ืฉื˜ ื‘ืึทื˜ืจืึทื›ื˜ืŸ Neo4j ื•ื•ื™ื™ึทืœ ืงืœืึทืกื˜ืขืจื™ื ื’ ืจื™ืงื•ื•ื™ื™ืขืจื– ืึท ื’ืขืฉืขืคื˜ ื•ื•ืขืจืกื™ืข, ื“ืึธืก ืื™ื–, ื“ืขืจ ืคึผืจืึธื“ื•ืงื˜ ืื™ื– ื ื™ืฉื˜ ืึธืคึฟืŸ ืžืงื•ืจ.

ื’ืจืึทืคื™ืง ื“ื‘ืžืก ื–ืึธื’ืŸ: "ืื•ื™ื‘ ืขืก ืงื•ืงื˜ ื•ื•ื™ ืึท ื’ืจืึทืคื™ืง, ืžื™ื™ึทื›ืœ ืขืก ื•ื•ื™ ืึท ื’ืจืึทืคื™ืง!" - ืฉื™ื™ื ืงื™ื™ื˜!

ืขืจืฉื˜ืขืจ, ืื™ืš ื’ืขืฆื•ื™ื’ืŸ ืึท ื’ืจืึทืคื™ืง, ื•ื•ืึธืก ืื™ื– ื’ืขืžืื›ื˜ ืคึผื•ื ืงื˜ ืœื•ื™ื˜ ื“ื™ ืงืึทื ืึทื ื– ืคื•ืŸ ื’ืจืึทืคื™ืง ื“ื‘ืžืก:

ืึทืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ื˜ืขืกื˜ื™ื ื’ ื“ื™ ืึธื ื•ื•ืขื ื“ืœืขืš ืคื•ืŸ ื“ื™ JanusGraph ื’ืจืึทืคื™ืง 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()

ื•ื•ืึธืก ืื™ืŸ ืจื•ืกื™ืฉ ืื™ื– ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก: ื’ืขืคึฟื™ื ืขืŸ ืึท ื–ืึธื ืข ืžื™ื˜ ID=0, ื ืขืžืขืŸ ืึทืœืข ื“ื™ ื•ื•ืขืจื˜ื™ืงืก ืคื•ืŸ ื•ื•ืึธืก ืึท ื‘ืจืขื’ ื’ื™ื™ื˜ ืฆื• ืื™ื (ื–ืึธื ืขืกื˜ืขืคึผ), ืกื˜ืึทืžืคึผ ืึธืŸ ื’ื™ื™ืŸ ืฆื•ืจื™ืง ื‘ื™ื– ืื™ืจ ื’ืขืคึฟื™ื ืขืŸ ื“ื™ ื–ืึธื ืขืกื˜ืขืคึผืก ืคื•ืŸ ื•ื•ืึธืก ืขืก ืื™ื– ืึท ื‘ืจืขื’ ืฆื• ื“ื™ ื–ืึธื ืข ืžื™ื˜ ID=19, ืฆื™ื™ืœืŸ ื“ื™ ื ื•ืžืขืจ ืึทื–ืึท ืงื™ื™ื˜ืŸ.

ืื™ืš ื˜ืึธืŸ ื ื™ื˜ ืคืึทืจื”ื™ื˜ืŸ ืฆื• ื•ื•ื™ืกืŸ ืึทืœืข ื“ื™ ื™ื ื˜ืจืึทืงืึทืกื™ื– ืคื•ืŸ ื–ื•ื›ืŸ ืื•ื™ืฃ ื’ืจืึทืคืก, ืึธื‘ืขืจ ื“ื™ ืึธื ืคึฟืจืขื’ ืื™ื– ื’ืขื•ื•ืขืŸ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ืขื ื‘ื•ืš (https://kelvinlawrence.net/book/Gremlin-Graph-Guide.html).

ืื™ืš ืœืึธื•ื“ื™ื“ 50 ื˜ื•ื™ื–ื ื˜ ื˜ืจืึทืงืก ืจื™ื™ื ื“ื–ืฉื™ื ื’ ืคื•ืŸ 3 ืฆื• 20 ืคื•ื ืงื˜ืŸ ืื™ืŸ ืœืขื ื’ ืื™ืŸ ืึท JanusGraph ื’ืจืึทืคื™ืง ื“ืึทื˜ืึทื‘ื™ื™ืก ื ื™ืฆืŸ ื“ื™ BerkeleyDB ื‘ืึทืงืขื ื“, ื‘ืืฉืืคืŸ ื™ื ื“ืขืงืกื™ื– ืœื•ื™ื˜ ืฆื• ืคื™ืจืขืจืฉืึทืคื˜.

ืคึผื™ื˜ื”ืึธืŸ ืืจืืคืงืืคื™ืข ืฉืจื™ืคื˜:


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 ืงืึธืจืขืก ืื•ืŸ 16 ื’ื™ื’ืื‘ื™ื™ื˜ ื‘ืึทืจืึทืŸ ืื•ื™ืฃ ืึท ืกืกื“. JanusGraph ืื™ื– ื’ืขื•ื•ืขืŸ ื“ื™ืคึผืœื•ื™ื“ ืžื™ื˜ ื“ืขื ื‘ืึทืคึฟืขืœ:

docker run --name janusgraph -p8182:8182 janusgraph/janusgraph:latest

ืื™ืŸ ื“ืขื ืคืึทืœ, ื“ื™ ื“ืึทื˜ืŸ ืื•ืŸ ื™ื ื“ืขืงืกื™ื– ื•ื•ืึธืก ื–ืขื ืขืŸ ื’ืขื ื™ืฆื˜ ืคึฟืึทืจ ืคึผื™ื ื˜ืœืขืš ื’ืœื™ื™ึทื›ืŸ ืึธื ืคึฟืจืขื’ืŸ ื–ืขื ืขืŸ ืกื˜ืึธืจื“ ืื™ืŸ BerkeleyDB. ืื™ืš ื”ืื‘ ื“ื•ืจื›ื’ืขืคื™ืจื˜ ื“ื™ ืคืจื™ืขืจื“ื™ื’ืข ื‘ืงืฉื”, ื”ืื‘ ืื™ืš ื‘ืืงื•ืžืขืŸ ื ืฆื™ื™ื˜ ื’ืœื™ื™ืš ืฆื• ืขื˜ืœื™ื›ืข ืฆืขื ื“ืœื™ื’ืขืจ ืกืขืงื•ื ื“ืขืก.

ื“ื•ืจืš ืœื•ื™ืคืŸ ื“ื™ 4 ืื•ื™ื‘ืŸ ืกืงืจื™ืคึผืก ืื™ืŸ ืคึผืึทืจืึทืœืขืœ, ืื™ืš ื’ืขืจืื˜ืŸ ืฆื• ื•ื•ืขื ื“ืŸ ื“ื™ DBMS ืื™ืŸ ืึท ืงื™ืจื‘ืขืก ืžื™ื˜ ืึท ืคืจื™ื™ืœืขืš ื˜ื™ื™ึทืš ืคื•ืŸ ื“ื–ืฉืึทื•ื•ืึท ืกื˜ืึทืงืงื˜ืจืึทืกืขืก (ืื•ืŸ ืžื™ืจ ืึทืœืข ืœื™ื‘ ืœื™ื™ืขื ืขืŸ ื“ื–ืฉืึทื•ื•ืึท ืกื˜ืึทืงืงื˜ืจืึทืกืขืก) ืื™ืŸ ื“ื™ ื“ืึธืงืงืขืจ ืœืึธื’ืก.

ื ืึธืš ืขื˜ืœืขื›ืข ื’ืขื“ืึทื ืง, ืื™ืš ื‘ืึทืฉืœืึธืกืŸ ืฆื• ืคืึทืจืคึผืึธืฉืขื˜ืขืจืŸ ื“ื™ ื’ืจืึทืคื™ืง ื“ื™ืึทื’ืจืึทืžืข ืฆื• ื“ื™ ืคืืœื’ืขื ื“ืข:

ืึทืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ื˜ืขืกื˜ื™ื ื’ ื“ื™ ืึธื ื•ื•ืขื ื“ืœืขืš ืคื•ืŸ ื“ื™ JanusGraph ื’ืจืึทืคื™ืง DBMS ืคึฟืึทืจ ืกืึทืœื•ื•ื™ื ื’ ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ื“ืขืจื’ื™ื™ื•ื ื’ ืคึผืึทืกื™ืง ืคึผืึทื˜ืก

ื‘ืึทืฉืœืึธืกืŸ ืึทื– ื–ื•ื›ืŸ ื“ื•ืจืš ืขื ื˜ื™ื˜ื™ ืึทื˜ืจืึทื‘ื™ื•ืฅ ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ืคืึทืกื˜ืขืจ ื•ื•ื™ ื–ื•ื›ืŸ ื“ื•ืจืš ืขื“ื–ืฉืึทื–. ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ืžื™ื™ืŸ ื‘ืงืฉื” ืื™ื– ื’ืขื•ื•ืืจืŸ ื“ื™ ืคืืœื’ืขื ื“ืข:

g.V().hasLabel('ZoneStep').has('id',0).repeat(__.out().simplePath()).until(__.hasLabel('ZoneStep').has('id',19)).count().next()

ื•ื•ืึธืก ืื™ืŸ ืจื•ืกื™ืฉ ืื™ื– ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก: ื’ืขืคึฟื™ื ืขืŸ ZoneStep ืžื™ื˜ ID=0, ืกื˜ืึทืžืคึผ ืึธืŸ ื’ื™ื™ืŸ ืฆื•ืจื™ืง ื‘ื™ื– ืื™ืจ ื’ืขืคึฟื™ื ืขืŸ ZoneStep ืžื™ื˜ ID=19, ืฆื™ื™ืœืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืึทื–ืึท ืงื™ื™ื˜ืŸ.

ืื™ืš ืื•ื™ืš ืกื™ืžืคึผืœืึทืคื™ื™ื“ ื“ื™ ืœืึธื•ื“ื™ื ื’ ืฉืจื™ืคื˜ ื’ืขื’ืขื‘ืŸ ืื•ื™ื‘ืŸ ืื™ืŸ ืกื“ืจ ื ื™ืฉื˜ ืฆื• ืฉืึทืคึฟืŸ ื•ืžื ื™ื™ื˜ื™ืง ืงืึทื ืขืงืฉืึทื ื–, ืœื™ืžื™ื˜ืขื“ ื–ื™ืš ืฆื• ืึทื˜ืจื™ื‘ื™ื•ืฅ.

ื“ื™ ื‘ืงืฉื” ื”ืึธื˜ ื ืึธืš ื’ืขื ื•ืžืขืŸ ืขื˜ืœืขื›ืข ืกืขืงื•ื ื“ืขืก ืฆื• ืคืึทืจืขื ื“ื™ืงืŸ, ื•ื•ืึธืก ืื™ื– ื’ืขื•ื•ืขืŸ ื’ืึธืจ ืึทื ืึทืงืกืขืคึผื˜ืึทื‘ืึทืœ ืคึฟืึทืจ ืื•ื ื“ื–ืขืจ ืึทืจื‘ืขื˜, ื•ื•ื™ื™ึทืœ ืขืก ืื™ื– ื ื™ืฉื˜ ืคึผืึทืกื™ืง ืคึฟืึทืจ ื“ื™ ืฆื•ื•ืขืงืŸ ืคื•ืŸ ืึทื“ื”ืึธืง ืจื™ืงื•ื•ืขืก ืคื•ืŸ ืงื™ื™ืŸ ืžื™ืŸ.

ืื™ืš ื’ืขืคืจื•ื•ื•ื˜ ื“ื™ืคึผืœื•ื™ื™ื ื’ JanusGraph ื ื™ืฆืŸ Scylla ื•ื•ื™ ื“ื™ ืคืึทืกื˜ืึทืกื˜ ืงืึทืกืกืึทื ื“ืจืึท ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ, ืึธื‘ืขืจ ื“ืึธืก ืื•ื™ืš ื”ืื˜ ื ื™ืฉื˜ ืคื™ืจืŸ ืฆื• ืงื™ื™ืŸ ื‘ืึทื˜ื™ื™ื˜ื™ืง ืคืึธืจืฉื˜ืขืœื•ื ื’ ืขื ื“ืขืจื•ื ื’ืขืŸ.

ืึทื–ื•ื™ ื˜ืจืึธืฅ ื“ืขื ืคืึทืงื˜ ืึทื– "ืขืก ืงื•ืงื˜ ื•ื•ื™ ืึท ื’ืจืึทืคื™ืง", ืื™ืš ืงืขืŸ ื ื™ืฉื˜ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื’ืจืึทืคื™ืง DBMS ืฆื• ืคึผืจืึทืกืขืกื˜ ืขืก ื’ืขืฉื•ื•ื™ื ื“. ืื™ืš ื’ืึธืจ ื™ื‘ืขืจื ืขืžืขืŸ ืึทื– ืขืก ืื™ื– ืขืคึผืขืก ืื™ืš ื˜ืึธืŸ ื ื™ื˜ ื•ื•ื™ืกืŸ ืื•ืŸ ืึทื– JanusGraph ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืžืื›ื˜ ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื“ืขื ื–ื•ื›ืŸ ืื™ืŸ ืึท ื‘ืจืึธื›ืฆืึธืœ ืคื•ืŸ ืึท ืจื’ืข, ืึธื‘ืขืจ, ืื™ืš ืงืขืŸ ื ื™ืฉื˜ ื˜ืึธืŸ ื“ืึธืก.

ื–ื™ื ื˜ ื“ื™ ืคึผืจืึธื‘ืœืขื ื ืึธืš ื“ืืจืฃ ืฆื• ื–ื™ื™ืŸ ืกืึทืœื•ื•ื“, ืื™ืš ืื ื’ืขื”ื•ื™ื‘ืŸ ืฆื• ื˜ืจืึทื›ื˜ืŸ ื•ื•ืขื’ืŸ JOINs ืื•ืŸ ืคึผื™ื•ื•ืึธืฅ ืคื•ืŸ ื˜ื™ืฉืŸ, ื•ื•ืึธืก ื”ืื˜ ื ื™ืฉื˜ ื™ื ืกืคึผื™ืจื™ืจืŸ ืึธืคึผื˜ื™ืžื™ื–ื ืื™ืŸ ื˜ืขืจืžื™ื ืขืŸ ืคื•ืŸ ืขืœืึทื’ืึทื ืก, ืึธื‘ืขืจ ืงืขืŸ ื–ื™ื™ืŸ ืึท ื’ืึธืจ ื•ื•ืขืจืงืึทื‘ืึทืœ ืึธืคึผืฆื™ืข ืื™ืŸ ืคื™ืจ.

ืื•ื ื“ื–ืขืจ ืคึผืจื•ื™ืขืงื˜ ืฉื•ื™ืŸ ื ื™ืฆื˜ Apache ClickHouse, ืึทื–ื•ื™ ืื™ืš ื‘ืึทืฉืœืึธืกืŸ ืฆื• ืคึผืจื•ื‘ื™ืจืŸ ืžื™ื™ืŸ ืคืึธืจืฉื•ื ื’ ืื•ื™ืฃ ื“ืขื ืึทื ืึทืœื™ื˜ื™ืฉ DBMS.

ื“ื™ืคึผืœื•ื™ื“ ืงืœื™ืงื›ืึธื•ืกืข ืžื™ื˜ ืึท ืคึผืฉื•ื˜ ืจืขืฆืขืคึผื˜:

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. ืฆื• ืžืึทืš ืคื•ืŸ ืคื•ื ื˜ ื ืฆื• ืคื•ื ื˜ ื‘:

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 ืกืขืงื•ื ื“ืขืก. ื“ืึธ ืื™ื– ืึท ื‘ื™ื™ืฉืคึผื™ืœ ืคื•ืŸ ื“ื™ ืึธื ืคึฟืจืขื’ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืฆื™ื™ื˜ ืคึฟืึทืจ ืฆื™ื™ืœืŸ (*) ื’ื™ื™ื˜ ืคืืจื‘ื™ื™ ื“ื•ืจืš 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.

ื“ื™ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืื™ื– ืึทื–ื•ื™ ื’ื•ื˜ ืึทื– ืžื™ืจ ืžื™ืกื˜ืึธืžืข ื•ื•ืขื˜ ื ื™ืฉื˜ ืืคื™ืœื• ื”ืึธื‘ืŸ ืฆื• ื˜ืจืึทื›ื˜ืŸ ื•ื•ืขื’ืŸ ืคึผื™ื•ื•ืึทื˜ื™ื ื’ ื˜ื™ืฉืŸ ืคึผืจืึธื’ืจืึทืžืžืึทื˜ื™ืง. ื‘ื™ื– ืึทื”ืขืจ, ืžื™ืจ ื”ืึธื‘ืŸ ืฆื• ื˜ืึธืŸ ืคึผื™ื•ื•ืึทืฅ ืคื•ืŸ ื“ืึทื˜ืŸ ืจื™ื˜ืจื™ื•ื•ื“ ืคึฟื•ืŸ ื•ื•ืขืจื˜ื™ืงืึท ื“ื•ืจืš ื•ืคึผืœืึธืึทื“ ืฆื• ืึทืคึผืึทื˜ืฉื™ ืคึผืึทืจืงื•ื•ืขื˜.

ืฆื•ื ื‘ืึทื“ื•ื™ืขืจืŸ, ืืŸ ืื ื“ืขืจ ืคึผืจื•ื•ื•ืŸ ืฆื• ื ื•ืฆืŸ ืึท ื’ืจืึทืคื™ืง DBMS ืื™ื– ื ื™ื˜ ื’ืขืจืึธื˜ืŸ. ืื™ืš ื”ืึธื‘ ื ื™ื˜ ื’ืขืคึฟื•ื ืขืŸ JanusGraph ืฆื• ื”ืึธื‘ืŸ ืึท ืคืจื™ื™ึทื ื“ืœืขืš ื™ืงืึธื•ืกื™ืกื˜ืึทื ื•ื•ืึธืก ื’ืขืžืื›ื˜ ืขืก ื’ืจื™ื ื’ ืฆื• ื‘ืึทืงื•ืžืขืŸ ืึทืจื•ื™ืฃ ืฆื• ื“ื™ ืคึผืจืึธื“ื•ืงื˜. ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ืฆื• ืงืึทื ืคื™ื’ื™ืขืจ ื“ื™ ืกืขืจื•ื•ืขืจ, ื“ื™ ื˜ืจืื“ื™ืฆื™ืื ืขืœืŸ ื–'ืื‘ื ื•ื•ืขื’ ืื™ื– ื’ืขื ื™ืฆื˜, ื•ื•ืึธืก ื•ื•ืขื˜ ืžืึทื›ืŸ ืžืขื ื˜ืฉืŸ ื•ื•ืึธืก ื–ืขื ืขืŸ ื ื™ืฉื˜ ื‘ืึทืงืึทื ื˜ ืžื™ื˜ ื–'ืื‘ื ื•ื•ื™ื™ื ืขืŸ ื˜ืจืขืจืŸ ืคื•ืŸ ื‘ืœื•ื˜:

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.

ื“ื™ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ ืื™ื– ื’ืึทื ืฅ ืงืจื•ื ืื™ืŸ ื˜ืขืจืžื™ื ืขืŸ ืคื•ืŸ ื™ื ื“ืขืงืกื™ื–, ื–ื™ื ื˜ ืึธื ืคื™ืจื•ื ื’ ื™ื ื“ืขืงืกื™ื– ืจื™ืงื•ื•ื™ื™ืขืจื– ืื™ืจ ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ืขื˜ืœืขื›ืข ื’ืึทื ืฅ ืžืึธื“ื ืข ืฉืึทืžืึทื ื™ืกื ืื™ืŸ ื’ืจืึธืึธื•ื•ื™. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืงืจื™ื™ื™ื˜ื™ื ื’ ืึทืŸ ืื™ื ื“ืขืงืก ืžื•ื–ืŸ ื–ื™ื™ืŸ ื’ืขื˜ืืŸ ื“ื•ืจืš ืฉืจื™ื™ื‘ืŸ ืงืึธื“ ืื™ืŸ ื“ื™ ื’ืจืขืžืœื™ืŸ ืงืึทื ืกืึธื•ืœ (ื•ื•ืึธืก, ื“ื•ืจืš ื“ืขื ื•ื•ืขื’, ื˜ื•ื˜ ื ื™ืฉื˜ ืึทืจื‘ืขื˜ืŸ ืื•ื™ืก ืคื•ืŸ ื“ื™ ืงืขืกื˜ืœ). ืคึฟื•ืŸ ื“ืขืจ ื‘ืึทืึทืžื˜ืขืจ 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()

ืึทืคื˜ืขืจื•ื•ืึธืจื“

ืื™ืŸ ืึท ื–ื™ื ืขืŸ, ื“ืขืจ ืื•ื™ื‘ืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ืื™ื– ืึท ืคืึทืจื’ืœื™ื™ึทืš ืฆื•ื•ื™ืฉืŸ ื•ื•ืึทืจืขื ืื•ืŸ ื•ื•ื™ื™ืš. ืื•ื™ื‘ ืื™ืจ ื˜ืจืึทื›ื˜ืŸ ื•ื•ืขื’ืŸ ืื™ื, ืึท ื’ืจืึทืคื™ืง DBMS ืคึผืขืจืคืึธืจืžื– ืื ื“ืขืจืข ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื–ืขืœื‘ืข ืจืขื–ื•ืœื˜ืึทื˜ืŸ. ืึธื‘ืขืจ, ื•ื•ื™ ืึท ื˜ื™ื™ืœ ืคื•ืŸ ื“ื™ ื˜ืขืกืฅ, ืื™ืš ืื•ื™ืš ื’ืขืคื™ืจื˜ ืึทืŸ ืขืงืกืคึผืขืจื™ืžืขื ื˜ ืžื™ื˜ ืึท ื‘ืงืฉื” ื•ื•ื™:

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. ื“ื™ ื ื•ืฆืŸ ืคืึทืœ ื“ืขืจืœืื ื’ื˜ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ื– ืึท ืงืœืึธืจ ืึทื ื˜ื™-ืžื•ืกื˜ืขืจ ืคึฟืึทืจ ื’ืจืึทืคื™ืง ื“ื‘ืžืก, ื›ืึธื˜ืฉ ืขืก ืžื™ื™ื ื˜ ืคึผืึทืกื™ืง ืคึฟืึทืจ ืžืึธื“ืขืœื™ื ื’ ืื™ืŸ ื–ื™ื™ืขืจ ืคึผืขืจืึทื“ื™ื™ื.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’