рдЙрдкрдпреБрдХреНрдд рдорд╛рд░реНрдЧрд╣рд░реВ рдЦреЛрдЬреНрдиреЗ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ JanusGraph рдЧреНрд░рд╛рдл DBMS рдХреЛ рдкреНрд░рдпреЛрдЧрд╢реАрд▓рддрд╛ рдкрд░реАрдХреНрд╖рдг рдЧрд░реНрдиреЗ рдПрдХ рдкреНрд░рдпреЛрдЧ

рдЙрдкрдпреБрдХреНрдд рдорд╛рд░реНрдЧрд╣рд░реВ рдЦреЛрдЬреНрдиреЗ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ JanusGraph рдЧреНрд░рд╛рдл DBMS рдХреЛ рдкреНрд░рдпреЛрдЧрд╢реАрд▓рддрд╛ рдкрд░реАрдХреНрд╖рдг рдЧрд░реНрдиреЗ рдПрдХ рдкреНрд░рдпреЛрдЧ

рдирдорд╕реНрддреЗ рд╕рдмреИред рд╣рд╛рдореА рдЕрдлрд▓рд╛рдЗрди рдЯреНрд░рд╛рдлрд┐рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдгрдХреЛ рд▓рд╛рдЧрд┐ рдЙрддреНрдкрд╛рджрди рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрджреИрдЫреМрдВред рдкрд░рд┐рдпреЛрдЬрдирд╛рд╕рдБрдЧ рдХреНрд╖реЗрддреНрд░рд╣рд░реВрдорд╛ рдЖрдЧрдиреНрддреБрдХ рдорд╛рд░реНрдЧрд╣рд░реВрдХреЛ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рд╡рд┐рд╢реНрд▓реЗрд╖рдгрд╕рдБрдЧ рд╕рдореНрдмрдиреНрдзрд┐рдд рдХрд╛рд░реНрдп рдЫред

рдпрд╕ рдХрд╛рд░реНрдпрдХреЛ рднрд╛рдЧрдХреЛ рд░реВрдкрдорд╛, рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд╣рд░реВрд▓реЗ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░рдХрд╛ рдкреНрд░рдгрд╛рд▓реА рдкреНрд░рд╢реНрдирд╣рд░реВ рд╕реЛрдзреНрди рд╕рдХреНрдЫрдиреН:

  • рдХреНрд╖реЗрддреНрд░ "A" рдмрд╛рдЯ рдХреНрд╖реЗрддреНрд░ "B" рдорд╛ рдХрддрд┐ рдЖрдЧрдиреНрддреБрдХрд╣рд░реВ рдЧрдП;
  • рдХрддрд┐ рдЖрдЧрдиреНрддреБрдХрд╣рд░реВ рдХреНрд╖реЗрддреНрд░ "A" рдмрд╛рдЯ рдХреНрд╖реЗрддреНрд░ "B" рдорд╛ рдХреНрд╖реЗрддреНрд░ "C" рд░ рддреНрдпрд╕рдкрдЫрд┐ рдХреНрд╖реЗрддреНрд░ "D" рдорд╛рд░реНрдлрдд рдЧрдП;
  • рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░рдХреЛ рдЖрдЧрдиреНрддреБрдХрд▓рд╛рдИ рдХреНрд╖реЗрддреНрд░ "A" рдмрд╛рдЯ рдХреНрд╖реЗрддреНрд░ "B" рд╕рдореНрдо рдпрд╛рддреНрд░рд╛ рдЧрд░реНрди рдХрддрд┐ рд╕рдордп рд▓рд╛рдЧреНрдпреЛред

рд░ рдзреЗрд░реИ рд╕рдорд╛рди рд╡рд┐рд╢реНрд▓реЗрд╖рдгрд╛рддреНрдордХ рдкреНрд░рд╢реНрдирд╣рд░реВред

рдХреНрд╖реЗрддреНрд░рд╣рд░реВрдорд╛ рдЖрдЧрдиреНрддреБрдХрдХреЛ рдЖрд╡рд╛рдЧрдорди рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдЧреНрд░рд╛рдл рд╣реЛред рдЗрдиреНрдЯрд░рдиреЗрдЯ рдкрдвреЗрдкрдЫрд┐, рдореИрд▓реЗ рдкрддреНрддрд╛ рд▓рдЧрд╛рдПрдБ рдХрд┐ рдЧреНрд░рд╛рдл рдбреАрдмреАрдПрдордПрд╕рд╣рд░реВ рд╡рд┐рд╢реНрд▓реЗрд╖рдгрд╛рддреНрдордХ рд░рд┐рдкреЛрд░реНрдЯрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдкрдирд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫред рдЧреНрд░рд╛рдл DBMS рд▓реЗ рддреНрдпрд╕реНрддрд╛ рдкреНрд░рд╢реНрдирд╣рд░реВрдХреЛ рд╕рд╛рдордирд╛ рдХрд╕рд░реА рдЧрд░реНрдиреЗрдЫ рднрдиреНрдиреЗ рд╣реЗрд░реНрди рдореЗрд░реЛ рдЗрдЪреНрдЫрд╛ рдерд┐рдпреЛ (TL; DR; рдЦрд░рд╛рдм)ред

рдореИрд▓реЗ DBMS рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд░реЛрдЬреЗрдВ рдЬрд╛рдирд╕рдЧреНрд░рд╛рдл, рдЧреНрд░рд╛рдл рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд DBMS рдХреЛ рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдХреЛ рд░реВрдкрдорд╛, рдЬреБрди рдкрд░рд┐рдкрдХреНрд╡ рдкреНрд░рд╡рд┐рдзрд┐рд╣рд░реВрдХреЛ рд╕реНрдЯреНрдпрд╛рдХрдорд╛ рдирд┐рд░реНрднрд░ рдЧрд░реНрджрдЫ, рдЬрд╕рд▓реЗ (рдореЗрд░реЛ рд╡рд┐рдЪрд╛рд░рдорд╛) рдпрд╕рд▓рд╛рдИ рд╕рднреНрдп рдкрд░рд┐рдЪрд╛рд▓рди рд╡рд┐рд╢реЗрд╖рддрд╛рд╣рд░реВ рдкреНрд░рджрд╛рди рдЧрд░реНрдиреБрдкрд░реНрдЫ:

  • BerkeleyDB рднрдгреНрдбрд╛рд░рдг рдмреНрдпрд╛рдХрдПрдиреНрдб, Apache Cassandra, Scylla;
  • рдЬрдЯрд┐рд▓ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рд╣рд░реВ рд▓реБрд╕реЗрди, Elasticsearch, Solr рдорд╛ рднрдгреНрдбрд╛рд░рдг рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред

JanusGraph рдХреЛ рд▓реЗрдЦрдХрд╣рд░реВрд▓реЗ рд▓реЗрдЦреНрдЫрдиреН рдХрд┐ рдпреЛ OLTP рд░ OLAP рджреБрд╡реИрдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рдЫред

рдореИрд▓реЗ BerkeleyDB, Apache Cassandra, Scylla рд░ ES рд╕рдБрдЧ рдХрд╛рдо рдЧрд░реЗрдХреЛ рдЫреБ, рд░ рдпреА рдЙрддреНрдкрд╛рджрдирд╣рд░реВ рдкреНрд░рд╛рдпрдГ рд╣рд╛рдореНрд░реЛ рдкреНрд░рдгрд╛рд▓реАрд╣рд░реВрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ, рддреНрдпрд╕реИрд▓реЗ рдо рдпреЛ рдЧреНрд░рд╛рдл DBMS рдкрд░реАрдХреНрд╖рдгрдХреЛ рдмрд╛рд░реЗрдорд╛ рдЖрд╢рд╛рд╡рд╛рджреА рдерд┐рдПрдБред рдорд▓рд╛рдИ RocksDB рдорд╛ BerkeleyDB рдЫрдиреЛрдЯ рдЧрд░реНрди рдЕрдиреМрдареЛ рд▓рд╛рдЧреНрдпреЛ, рддрд░ рдпреЛ рд╕рдореНрднрд╡рддрдГ рд▓реЗрдирджреЗрди рдЖрд╡рд╢реНрдпрдХрддрд╛рд╣рд░реВрдХреЛ рдХрд╛рд░рдгрд▓реЗ рд╣реЛред рдХреБрдиреИ рдкрдирд┐ рдЕрд╡рд╕реНрдерд╛рдорд╛, рд╕реНрдХреЗрд▓реЗрдмрд▓, рдЙрддреНрдкрд╛рджрди рдкреНрд░рдпреЛрдЧрдХреЛ рд▓рд╛рдЧрд┐, рдпреЛ рдХреНрдпрд╛рд╕рд╛рдиреНрдбреНрд░рд╛ рд╡рд╛ Scylla рдорд╛ рдмреНрдпрд╛рдХрдЗрдиреНрдб рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕реБрдЭрд╛рд╡ рджрд┐рдЗрдПрдХреЛ рдЫред

рдореИрд▓реЗ Neo4j рд▓рд╛рдИ рд╡рд┐рдЪрд╛рд░ рдЧрд░реЗрди рдХрд┐рдирднрдиреЗ рдХреНрд▓рд╕реНрдЯрд░рд┐рдЩрд▓рд╛рдИ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рд╕рдВрд╕реНрдХрд░рдг рдЪрд╛рд╣рд┐рдиреНрдЫ, рддреНрдпреЛ рд╣реЛ, рдЙрддреНрдкрд╛рджрди рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд рд╣реЛрдЗрдиред

рдЧреНрд░рд╛рдл DBMSs рднрдиреНрдЫрдиреН: "рдпрджрд┐ рдпреЛ рдЧреНрд░рд╛рдл рдЬрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ, рдпрд╕рд▓рд╛рдИ рдЧреНрд░рд╛рдл рдЬрд╕реНрддреИ рд╡реНрдпрд╡рд╣рд╛рд░ рдЧрд░реНрдиреБрд╣реЛрд╕реН!" - рд╕реМрдиреНрджрд░реНрдп!

рдкрд╣рд┐рд▓реЗ, рдореИрд▓реЗ рдЧреНрд░рд╛рдл рдХреЛрд░реЗрдВ, рдЬреБрди рдЧреНрд░рд╛рдл DBMSs рдХреЛ рдХреНрдпрд╛рдирдирд╣рд░реВ рдЕрдиреБрд╕рд╛рд░ рдмрдирд╛рдЗрдПрдХреЛ рдерд┐рдпреЛ:

рдЙрдкрдпреБрдХреНрдд рдорд╛рд░реНрдЧрд╣рд░реВ рдЦреЛрдЬреНрдиреЗ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ 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).

рдореИрд▓реЗ BerkeleyDB рдмреНрдпрд╛рдХрдЗрдиреНрдб рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ JanusGraph рдЧреНрд░рд╛рдл рдбрд╛рдЯрд╛рдмреЗрд╕рдорд╛ 50 рджреЗрдЦрд┐ 3 рдмрд┐рдиреНрджреБ рд▓рдореНрдмрд╛рдЗрдХрд╛ 20 рд╣рдЬрд╛рд░ рдЯреНрд░реНрдпрд╛рдХрд╣рд░реВ рд▓реЛрдб рдЧрд░реЗрдВ, рдЕрдиреБрд╕рд╛рд░ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдпреЛред рдиреЗрддреГрддреНрд╡.

рдкрд╛рдЗрдерди рдбрд╛рдЙрдирд▓реЛрдб рд╕реНрдХреНрд░рд┐рдкреНрдЯ:


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 рдХреЛрд░ рд░ 16 GB RAM рднрдПрдХреЛ VM рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдпреМрдВред JanusGraph рдпреЛ рдЖрджреЗрд╢ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рддреИрдирд╛рдд рдЧрд░рд┐рдПрдХреЛ рдерд┐рдпреЛ:

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

рдпрд╕ рдЕрд╡рд╕реНрдерд╛рдорд╛, рдбреЗрдЯрд╛ рд░ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рд╣рд░реВ рдЬреБрди рд╕рдЯреАрдХ рдорд┐рд▓рд╛рди рдЦреЛрдЬрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ BerkeleyDB рдорд╛ рднрдгреНрдбрд╛рд░рдг рдЧрд░рд┐рдиреНрдЫред рдкрд╣рд┐рд▓реЗ рджрд┐рдЗрдПрдХреЛ рдЕрдиреБрд░реЛрдз рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЧрд░рд┐рд╕рдХреЗрдкрдЫрд┐, рдореИрд▓реЗ рдзреЗрд░реИ рджрд╕реМрдВ рд╕реЗрдХреЗрдиреНрдб рдмрд░рд╛рдмрд░рдХреЛ рд╕рдордп рдкреНрд░рд╛рдкреНрдд рдЧрд░реЗрдВред

рдорд╛рдерд┐рдХрд╛ рек рд╡рдЯрд╛ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд╣рд░реВ рд╕рдорд╛рдирд╛рдиреНрддрд░рдорд╛ рдЪрд▓рд╛рдПрд░, рдореИрд▓реЗ DBMS рд▓рд╛рдИ рдЬрд╛рднрд╛ рд╕реНрдЯреНрдпрд╛рдХрдЯреНрд░реЗрд╕рд╣рд░реВ (рд░ рд╣рд╛рдореА рд╕рдмреИрд▓рд╛рдИ рдЬрд╛рднрд╛ рд╕реНрдЯреНрдпрд╛рдХрдЯреНрд░реЗрд╕рд╣рд░реВ рдкрдвреНрди рдордирдкрд░реНрдЫ) рдбрдХрд░ рд▓рдЧрд╣рд░реВрдорд╛ рд░рдорд╛рдЗрд▓реЛ рд╕реНрдЯреНрд░рд┐рдордХреЛ рд╕рд╛рде рдХрджреНрджреВрдорд╛ рдкрд░рд┐рдгрдд рдЧрд░реНрди рд╕рдлрд▓ рднрдпреЛред

рдХреЗрд╣рд┐ рд╕реЛрдЪ рдкрдЫрд┐, рдореИрд▓реЗ рдЧреНрд░рд╛рдл рд░реЗрдЦрд╛рдЪрд┐рддреНрд░рд▓рд╛рдИ рдирд┐рдореНрдирдорд╛ рд╕рд░рд▓ рдмрдирд╛рдЙрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реЗрдВ:

рдЙрдкрдпреБрдХреНрдд рдорд╛рд░реНрдЧрд╣рд░реВ рдЦреЛрдЬреНрдиреЗ рд╕рдорд╕реНрдпрд╛ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ JanusGraph рдЧреНрд░рд╛рдл DBMS рдХреЛ рдкреНрд░рдпреЛрдЧрд╢реАрд▓рддрд╛ рдкрд░реАрдХреНрд╖рдг рдЧрд░реНрдиреЗ рдПрдХ рдкреНрд░рдпреЛрдЧ

рдирд┐рдХрд╛рдп рд╡рд┐рд╢реЗрд╖рддрд╛рд╣рд░реВрджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬреА рдЧрд░реНрдиреБ рдХрд┐рдирд╛рд░рд╛рд╣рд░реВрджреНрд╡рд╛рд░рд╛ рдЦреЛрдЬреА рдЧрд░реНрдиреБрднрдиреНрджрд╛ рдЫрд┐рдЯреЛ рд╣реБрдиреЗрдЫ рднрдиреНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНрджреИред рдирддрд┐рдЬрд╛рдХреЛ рд░реВрдкрдорд╛, рдореЗрд░реЛ рдЕрдиреБрд░реЛрдз рдирд┐рдореНрдирдорд╛ рдкрд░рд┐рдгрдд рднрдпреЛ:

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

рд░реВрд╕реА рднрд╛рд╖рд╛рдорд╛ рдХреЗ рдпрд╕реНрддреЛ рдЫ: ID=0 рдХреЛ рд╕рд╛рде ZoneStep рдлреЗрд▓рд╛ рдкрд╛рд░реНрдиреБрд╣реЛрд╕реН, рддрдкрд╛рдИрдВрд▓реЗ ID=19 рд╕рдБрдЧ ZoneStep рдлреЗрд▓рд╛ рдирдкрд╛рдПрд╕рдореНрдо рдкрдЫрд╛рдбрд┐ рдирдЬрд╛рдЗрдХрди рд╕реНрдЯрдореНрдк рдЧрд░реНрдиреБрд╣реЛрд╕реН, рддреНрдпрд╕реНрддрд╛ рдЪреЗрдирд╣рд░реВрдХреЛ рд╕рдВрдЦреНрдпрд╛ рдЧрдгрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реНред

рдореИрд▓реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЬрдбрд╛рдирд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рдирдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ рдорд╛рдерд┐ рджрд┐рдЗрдПрдХреЛ рд▓реЛрдбрд┐рдЩ рд╕реНрдХреНрд░рд┐рдкреНрдЯрд▓рд╛рдИ рдкрдирд┐ рд╕рд░рд▓ рдмрдирд╛рдПрдХреЛ рдЫреБ, рдЖрдлреВрд▓рд╛рдИ рд╡рд┐рд╢реЗрд╖рддрд╛рд╣рд░реВрдорд╛ рд╕реАрдорд┐рдд рд░рд╛рдЦреНрджреИред

рдЕрдиреБрд░реЛрдз рдкреВрд░рд╛ рд╣реБрди рдЕрдЭреИ рдзреЗрд░реИ рд╕реЗрдХреЗрдиреНрдб рд▓рд╛рдЧреНрдпреЛ, рдЬреБрди рд╣рд╛рдореНрд░реЛ рдХрд╛рд░реНрдпрдХреЛ рд▓рд╛рдЧрд┐ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рдерд┐рдпреЛ, рдХрд┐рдирдХрд┐ рдпреЛ рдХреБрдиреИ рдкрдирд┐ рдкреНрд░рдХрд╛рд░рдХреЛ AdHoc рдЕрдиреБрд░реЛрдзрд╣рд░реВрдХреЛ рдЙрджреНрджреЗрд╢реНрдпрдХрд╛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рдерд┐рдПрдиред

рдореИрд▓реЗ JanusGraph рд▓рд╛рдИ Scylla рдХреЛ рд╕рдмреИрднрдиреНрджрд╛ рдЫрд┐рдЯреЛ Cassandra рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдирдХреЛ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реЗ, рддрд░ рдпрд╕рд▓реЗ рдХреБрдиреИ рдкрдирд┐ рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рдХрд╛рд░реНрдпрд╕рдореНрдкрд╛рджрди рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВ рдирд┐рдореНрддреНрдпрд╛рдЙрди рд╕рдХреЗрдиред

рддреНрдпрд╕реИрд▓реЗ "рдпреЛ рдЧреНрд░рд╛рдл рдЬрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ" рднрдиреНрдиреЗ рддрдереНрдпрдХреЛ рдмрд╛рд╡рдЬреБрдж, рдореИрд▓реЗ рдпрд╕рд▓рд╛рдИ рдЫрд┐рдЯреЛ рдкреНрд░рд╢реЛрдзрди рдЧрд░реНрди рдЧреНрд░рд╛рдл DBMS рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХрд┐рдиред рдо рдкреВрд░реНрдгрддрдпрд╛ рдорд╛рдиреНрдЫреБ рдХрд┐ рддреНрдпрд╣рд╛рдБ рдХреЗрд╣рд┐ рдЫ рдЬреБрди рдорд▓рд╛рдИ рдерд╛рд╣рд╛ рдЫреИрди рд░ JanusGraph рд▓рд╛рдИ рд╕реЗрдХреЗрдиреНрдбрдХреЛ рдПрдХ рдЕрдВрд╢рдорд╛ рдпреЛ рдЦреЛрдЬ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ, рддрдерд╛рдкрд┐, рдореИрд▓реЗ рдпреЛ рдЧрд░реНрди рд╕рдХреЗрдиред

рд╕рдорд╕реНрдпрд╛ рдЕрдЭреИ рд╕рдорд╛рдзрд╛рди рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рднрдПрдХреЛрд▓реЗ, рдореИрд▓реЗ рддрд╛рд▓рд┐рдХрд╛рдХреЛ JOIN рд░ Pivots рдмрд╛рд░реЗ рд╕реЛрдЪреНрди рдерд╛рд▓реЗрдВ, рдЬрд╕рд▓реЗ рд╕реБрдиреНрджрд░рддрд╛рдХреЛ рд╕рдиреНрджрд░реНрднрдорд╛ рдЖрд╢рд╛рд╡рд╛рджрд▓рд╛рдИ рдкреНрд░реЗрд░рд┐рдд рдЧрд░реНрджреИрди, рддрд░ рд╡реНрдпрд╡рд╣рд╛рд░рдорд╛ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдХрд╛рд░реНрдпрдпреЛрдЧреНрдп рд╡рд┐рдХрд▓реНрдк рд╣реБрди рд╕рдХреНрдЫред

рд╣рд╛рдореНрд░реЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд╣рд┐рд▓реЗ рдиреИ 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 рдкреНрд░рдпреЛрдЧ рдЧрд░реА рджреБрдИрд╡рдЯрд╛ рдкреНрд░рд╢реНрдирд╣рд░реВ рдирд┐рд░реНрдорд╛рдг рдЧрд░рд┐рдпреЛред рдмрд┐рдиреНрджреБ 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

рдЕрдиреБрд░реЛрдзрд╣рд░реВ, рдирд┐рд╕реНрд╕рдиреНрджреЗрд╣, рдзреЗрд░реИ рдбрд░рд▓рд╛рдЧреНрджреЛ рджреЗрдЦрд┐рдиреНрдЫ; рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдпреЛрдЧрдХреЛ рд▓рд╛рдЧрд┐, рддрдкрд╛рдИрдВрд▓реЗ рд╕рдлреНрдЯрд╡реЗрдпрд░ рдЬреЗрдирд░реЗрдЯрд░ рд╣рд╛рд░реНрдиреЗрд╕ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рдпрджреНрдпрдкрд┐, рддрд┐рдиреАрд╣рд░реВ рдХрд╛рдо рдЧрд░реНрдЫрдиреН рд░ рддрд┐рдиреАрд╣рд░реВ рдЫрд┐рдЯреЛ рдХрд╛рдо рдЧрд░реНрдЫрдиреНред рджреБрдмреИ рдкрд╣рд┐рд▓реЛ рд░ рджреЛрд╕реНрд░реЛ рдЕрдиреБрд░реЛрдзрд╣рд░реВ реж.рез рд╕реЗрдХреЗрдиреНрдб рднрдиреНрджрд╛ рдХрдордорд╛ рдкреВрд░рд╛ рд╣реБрдиреНрдЫрдиреНред рдпрд╣рд╛рдБ 0.1 рдмрд┐рдиреНрджреБрд╣рд░реВ рдорд╛рд░реНрдлрдд рдЧреБрдЬрд░рдиреЗ рдЧрдгрдирд╛ (*) рдХреЛ рд▓рд╛рдЧрд┐ рдХреНрд╡реЗрд░реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕рдордпрдХреЛ рдЙрджрд╛рд╣рд░рдг рд╣реЛ:

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 рдзреЗрд░реИ рдЙрдЪреНрдЪ рдерд┐рдпреЛред рдПрдХреИ рд╕рдордпрдорд╛, рдХреНрд▓рд┐рдХрд╣рд╛рдЙрд╕рд▓реЗ рдбрд┐рд╕реНрдХ рд╕рдмрд╕рд┐рд╕реНрдЯрдордорд╛ рдиреНрдпреВрдирддрдо рд▓реЛрдб рдЙрддреНрдкрдиреНрди рдЧрд░реНрдпреЛред

рдирд┐рд╖реНрдХрд░реНрд╖рдорд╛

рд╣рд╛рдореАрд▓реЗ рдпрд╕ рдкреНрд░рдХрд╛рд░рдХреЛ рдЕрдиреБрд░реЛрдз рд╕реЗрд╡рд╛ рдЧрд░реНрди рдХреНрд▓рд┐рдХрд╣рд╛рдЙрд╕ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдирд┐рд░реНрдгрдп рдЧрд░реНрдпреМрдВред рд╣рд╛рдореА рдЬрд╣рд┐рд▓реЗ рдкрдирд┐ рд╡рд╕реНрддреБрдЧрдд рджреГрд╢реНрдпрд╣рд░реВ рд░ рд╕рдорд╛рдирд╛рдиреНрддрд░реАрдХрд░рдг рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдХреНрд╡реЗрд░реАрд╣рд░реВрд▓рд╛рдИ рдХреНрд▓рд┐рдХрд╣рд╛рдЙрд╕рдорд╛ рд▓реЛрдб рдЧрд░реНрдиреБ рдЕрдШрд┐ рдЕрдкрд╛рдЪреЗ рдлреНрд▓рд┐рдВрдХ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдШрдЯрдирд╛ рд╕реНрдЯреНрд░рд┐рдорд▓рд╛рдИ рдкреВрд░реНрд╡-рдкреНрд░рд╢реЛрдзрди рдЧрд░реЗрд░ рдердк рдЕрдиреБрдХреВрд▓рди рдЧрд░реНрди рд╕рдХреНрдЫреМрдВред

рдкреНрд░рджрд░реНрд╢рди рдпрддрд┐ рд░рд╛рдореНрд░реЛ рдЫ рдХрд┐ рд╣рд╛рдореАрд▓реЗ рд╕рдореНрднрд╡рддрдГ рдкрд┐рднреЛрдЯрд┐рдЩреН рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВ рдкреНрд░реЛрдЧреНрд░рд╛рдореЗрдЯрд┐рдХ рд░реВрдкрдорд╛ рд╕реЛрдЪреНрдиреБрдкрд░реНрджреИрдиред рдкрд╣рд┐рд▓реЗ, рд╣рд╛рдореАрд▓реЗ Apache Parquet рдорд╛ рдЕрдкрд▓реЛрдб рдорд╛рд░реНрдлрдд Vertica рдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рдбрд╛рдЯрд╛рдХреЛ рдкрд┐рднреЛрдЯрд╣рд░реВ рдЧрд░реНрдиреБрдкрд░реНрдереНрдпреЛред

рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, рдЧреНрд░рд╛рдл 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}

рдореИрд▓реЗ рд╕рдВрдпреЛрдЧрд╡рд╢ JanusGraph рдХреЛ BerkeleyDB рд╕рдВрд╕реНрдХрд░рдг "рд░рд╛рдЦреНрдиреБ" рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдЧрд░реЗрдВред

рдХрд╛рдЧрдЬрд╛рддрд╣рд░реВ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рд╣рд░реВрдХреЛ рд╕рдиреНрджрд░реНрднрдорд╛ рдПрдХрджрдореИ рдмрд╛рдЩреНрдЧреЛ рдЫ, рдХрд┐рдирдХрд┐ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рд╣рд░реВ рдкреНрд░рдмрдиреНрдз рдЧрд░реНрди рддрдкрд╛рдИрдВрд▓реЗ рдЧреНрд░реЛрднреАрдорд╛ рдХреЗрд╣реА рдЕрдиреМрдареЛ рд╢рдордирд╡рд╛рдж рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрди рдЖрд╡рд╢реНрдпрдХ рдЫред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрди рдЧреНрд░реЗрдорд▓рд┐рди рдХрдиреНрд╕реЛрд▓рдорд╛ рдХреЛрдб рд▓реЗрдЦреЗрд░ рдЧрд░реНрдиреБрдкрд░реНрдЫ (рдЬрд╕рд▓реЗ, рдмрд╛рдХрд╕ рдмрд╛рд╣рд┐рд░ рдХрд╛рдо рдЧрд░реНрджреИрди)ред рдЖрдзрд┐рдХрд╛рд░рд┐рдХ 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()

рдЬрд╕рд▓реЗ рд╣рд┐рдбреНрдиреЗ рджреВрд░реАрд▓рд╛рдИ рдкреНрд░рддрд┐рдмрд┐рдореНрдмрд┐рдд рдЧрд░реНрджрдЫред рдпрджреНрдпрдкрд┐, рддреНрдпрд╕реНрддрд╛ рдбреЗрдЯрд╛рдорд╛ рдкрдирд┐, рдЧреНрд░рд╛рдл DBMS рд▓реЗ рдкрд░рд┐рдгрд╛рдорд╣рд░реВ рджреЗрдЦрд╛рдпреЛ рдЬреБрди рдХреЗрд╣реА рд╕реЗрдХреЗрдиреНрдбрднрдиреНрджрд╛ рдкрд░ рдЧрдПрдХреЛ рдерд┐рдпреЛ ... рдпреЛ, рдЕрд╡рд╢реНрдп рдкрдирд┐, рддреНрдпрд╣рд╛рдБ рдорд╛рд░реНрдЧрд╣рд░реВ рдерд┐рдП рднрдиреНрдиреЗ рддрдереНрдпрдХреЛ рдХрд╛рд░рдгрд▓реЗ рд╣реЛред 0 -> X -> Y ... -> 1, рдЬреБрди рдЧреНрд░рд╛рдл рдЗрдиреНрдЬрд┐рдирд▓реЗ рдкрдирд┐ рдЬрд╛рдБрдЪ рдЧрд░реНрдпреЛред

рдПрдХ рдкреНрд░рд╢реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдкрдирд┐ рдЬрд╕реНрддреИ:

g.V().hasLabel('ZoneStep').has('id',0).out().has('id',1)).count().next()

рдо рдПрдХ рд╕реЗрдХреЗрдиреНрдб рднрдиреНрджрд╛ рдХрдордХреЛ рдкреНрд░рд╢реЛрдзрди рд╕рдордп рд╕рдВрдЧ рдПрдХ рдЙрддреНрдкрд╛рджрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЕрд╕рдорд░реНрде рдерд┐рдПред

рдХрдерд╛рдХреЛ рдиреИрддрд┐рдХрддрд╛ рдпреЛ рд╣реЛ рдХрд┐ рдПрдХ рд╕реБрдиреНрджрд░ рд╡рд┐рдЪрд╛рд░ рд░ рдкреНрд░рддрд┐рдорд╛рдирд╛рддреНрдордХ рдореЛрдбреЗрд▓рд┐рдЩрд▓реЗ рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдордХреЛ рдиреЗрддреГрддреНрд╡ рдЧрд░реНрджреИрди, рдЬреБрди рдХреНрд▓рд┐рдХрд╣рд╛рдЙрд╕рдХреЛ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ рдзреЗрд░реИ рдЙрдЪреНрдЪ рджрдХреНрд╖рддрд╛рдХреЛ рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рди рдЧрд░рд┐рдПрдХреЛ рдЫред рдпрд╕ рд▓реЗрдЦрдорд╛ рдкреНрд░рд╕реНрддреБрдд рдЧрд░рд┐рдПрдХреЛ рдкреНрд░рдпреЛрдЧ рдХреЗрд╕ рдЧреНрд░рд╛рдл DBMS рдХреЛ рд▓рд╛рдЧрд┐ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рд░реЛрдзреА рдврд╛рдБрдЪрд╛ рд╣реЛ, рдпрджреНрдпрдкрд┐ рдпреЛ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдкреНрд░рддрд┐рдорд╛рдирдорд╛ рдореЛрдбреЗрд▓рд┐рдЩрдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреБрдХреНрдд рджреЗрдЦрд┐рдиреНрдЫред

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди