αž€αžΆαžšαž–αž·αžŸαŸ„αž’αž“αŸαžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αŸƒαž€αŸ’αžšαžΆαž αŸ’αžœ JanusGraph DBMS αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αž•αŸ’αž›αžΌαžœαžŸαž˜αžšαž˜αŸ’αž™

αž€αžΆαžšαž–αž·αžŸαŸ„αž’αž“αŸαžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αŸƒαž€αŸ’αžšαžΆαž αŸ’αžœ JanusGraph DBMS αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αž•αŸ’αž›αžΌαžœαžŸαž˜αžšαž˜αŸ’αž™

αžŸαž½αžŸαŸ’αžαžΈβ€‹αž’αŸ’αž“αž€β€‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‚αŸ’αž“αžΆαŸ” αž™αžΎαž„αž€αŸ†αž–αž»αž„αž”αž„αŸ’αž€αžΎαžαž•αž›αž·αžαž•αž›αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžœαž·αž—αžΆαž‚αž…αžšαžΆαž…αžšαžŽαŸαž€αŸ’αžšαŸ…αž”αžŽαŸ’αžαžΆαž‰αŸ” αž‚αž˜αŸ’αžšαŸ„αž„αž“αŸαŸ‡αž˜αžΆαž“αž—αžΆαžšαž€αž·αž…αŸ’αž…αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž€αžΆαžšαžœαž·αž—αžΆαž‚αžŸαŸ’αžαž·αžαž·αž“αŸƒαž•αŸ’αž›αžΌαžœαž’αŸ’αž“αž€αž‘αžŸαŸ’αžŸαž“αžΆαž“αŸ…αž‘αžΌαž‘αžΆαŸ†αž„αžαŸ†αž”αž“αŸ‹αŸ”

αž‡αžΆαž•αŸ’αž“αŸ‚αž€αž“αŸƒαž€αž·αž…αŸ’αž…αž€αžΆαžšαž“αŸαŸ‡ αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž’αžΆαž…αžŸαž½αžšαžŸαŸ†αžŽαž½αžšαž”αŸ’αžšαž–αŸαž“αŸ’αž’αž“αŸƒαž”αŸ’αžšαž—αŸαž‘αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ–

  • αžαžΎαž˜αžΆαž“αž˜αž“αž»αžŸαŸ’αžŸαž”αŸ‰αž»αž“αŸ’αž˜αžΆαž“αž“αžΆαž€αŸ‹αž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αž–αžΈαžαŸ†αž”αž“αŸ‹ "A" αž‘αŸ…αžαŸ†αž”αž“αŸ‹ "B";
  • αžαžΎαž˜αžΆαž“αž˜αž“αž»αžŸαŸ’αžŸαž”αŸ‰αž»αž“αŸ’αž˜αžΆαž“αž“αžΆαž€αŸ‹αž”αžΆαž“αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αžαŸ†αž”αž“αŸ‹ "A" αž‘αŸ…αžαŸ†αž”αž“αŸ‹ "B" αžαžΆαž˜αžšαž™αŸˆαžαŸ†αž”αž“αŸ‹ "C" αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αž†αŸ’αž›αž„αž€αžΆαžαŸ‹αžαŸ†αž”αž“αŸ‹ "D";
  • αžαžΎαžαŸ’αžšαžΌαžœαž…αŸ†αžŽαžΆαž™αž–αŸαž›αž”αŸ‰αž»αž“αŸ’αž˜αžΆαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αŸ’αž‰αŸ€αžœαž‘αŸαžŸαž…αžšαž”αŸ’αžšαž—αŸαž‘αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αž˜αž½αž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αŸ’αžœαžΎαžŠαŸ†αžŽαžΎαžšαž–αžΈαžαŸ†αž”αž“αŸ‹ "A" αž‘αŸ…αžαŸ†αž”αž“αŸ‹ "B" αŸ”

αž“αž·αž„αžŸαŸ†αžŽαž½αžšαžœαž·αž—αžΆαž‚αžŸαŸ’αžšαžŠαŸ€αž„αž‚αŸ’αž“αžΆαž˜αž½αž™αž…αŸ†αž“αž½αž“αŸ”

αž…αž›αž“αžΆαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‘αžŸαŸ’αžŸαž“αžΆαž“αŸ…αž‘αžΌαž‘αžΆαŸ†αž„αžαŸ†αž”αž“αŸ‹αž‚αžΊαž‡αžΆαž€αŸ’αžšαžΆαž αŸ’αžœαžŠαžΉαž€αž“αžΆαŸ†αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž’αžΆαž“αž’αŸŠαžΈαž“αž’αžΊαžŽαž·αž αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžšαž€αžƒαžΎαž‰αžαžΆαž€αŸ’αžšαžΆαž αŸ’αžœ DBMS αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžšαž”αžΆαž™αž€αžΆαžšαžŽαŸαžœαž·αž—αžΆαž‚αž•αž„αžŠαŸ‚αžšαŸ” αžαŸ’αž‰αž»αŸ†αž˜αžΆαž“αž”αŸ†αžŽαž„αž”αŸ’αžšαžΆαžαŸ’αž“αžΆαž…αž„αŸ‹αž˜αžΎαž›αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž€αŸ’αžšαžΆαž αŸ’αžœ DBMSs αž“αžΉαž„αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž‡αžΆαž˜αž½αž™αž“αžΉαž„αžŸαŸ†αžŽαž½αžšαž”αŸ‚αž”αž“αŸαŸ‡ (TL; DR; αž˜αž·αž“αž›αŸ’αž’) αŸ”

αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž”αŸ’αžšαžΎ DBMS JanusGraphαž€αŸ’αž“αž»αž„αž“αžΆαž˜αž‡αžΆαž’αŸ’αž“αž€αžαŸ†αžŽαžΆαž„αžŠαŸαž†αŸ’αž“αžΎαž˜αž“αŸƒαž€αŸ’αžšαžΆαž αŸ’αžœαž·αž€αž”αŸ’αžšαž—αž–αž”αžΎαž€αž…αŸ†αž αžš 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αŸ–

αž€αžΆαžšαž–αž·αžŸαŸ„αž’αž“αŸαžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αŸƒαž€αŸ’αžšαžΆαž αŸ’αžœ 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()

αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‡αžΆαž—αžΆαžŸαžΆαžšαž»αžŸαŸ’αžŸαžΈαž‚αžΊαžŠαžΌαž…αž“αŸαŸ‡αŸ– αžŸαŸ’αžœαŸ‚αž„αžšαž€αžαŸ†αž”αž“αŸ‹αžŠαŸ‚αž›αž˜αžΆαž“αž›αŸαžαžŸαž˜αŸ’αž‚αžΆαž›αŸ‹ = 0 αž™αž€αž…αŸ†αž“αž»αž…αž€αŸ†αž–αžΌαž›αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžŠαŸ‚αž›αž‚αŸ‚αž˜αž˜αž½αž™αž‘αŸ…αžœαžΆ (ZoneStep) αžˆαž”αŸ‹αžŠαŸ„αž™αž˜αž·αž“αžαŸ’αžšαž›αž”αŸ‹αž€αŸ’αžšαŸ„αž™αžšαž αžΌαžαžŠαž›αŸ‹αž’αŸ’αž“αž€αžšαž€αžƒαžΎαž‰ ZoneSteps αž‘αžΆαŸ†αž„αž“αŸ„αŸ‡αžŠαŸ‚αž›αž˜αžΆαž“αž‚αŸ‚αž˜αž‘αŸ…αžαŸ†αž”αž“αŸ‹αž‡αžΆαž˜αž½αž™ ID=19 αžšαžΆαž”αŸ‹αž…αŸ†αž“αž½αž“αž…αŸ’αžšαžœαžΆαž€αŸ‹αž”αŸ‚αž”αž“αŸαŸ‡αŸ”

αžαŸ’αž‰αž»αŸ†β€‹αž˜αž·αž“β€‹αž’αŸ’αžœαžΎβ€‹αž–αž»αžβ€‹αž‡αžΆβ€‹αžŠαžΉαž„β€‹αž–αžΈβ€‹αž—αžΆαž–β€‹αžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰β€‹αž‘αžΆαŸ†αž„β€‹αž’αžŸαŸ‹β€‹αž“αŸƒβ€‹αž€αžΆαžšβ€‹αžŸαŸ’αžœαŸ‚αž„β€‹αžšαž€β€‹αž“αŸ…β€‹αž›αžΎβ€‹αž€αŸ’αžšαžΆαž αŸ’αžœβ€‹αž“αŸ„αŸ‡β€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžŸαŸ†αžŽαž½αžšβ€‹αž“αŸαŸ‡β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž”αž„αŸ’αž€αžΎαžβ€‹αž‘αžΎαž„β€‹αžŠαŸ„αž™β€‹αž•αŸ’αž’αŸ‚αž€β€‹αž›αžΎβ€‹αžŸαŸ€αžœαž—αŸ…β€‹αž“αŸαŸ‡ (https://kelvinlawrence.net/book/Gremlin-Graph-Guide.html).

αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž•αŸ’αž‘αž»αž€ 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 αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž–αžΈβ€‹αž”αžΆαž“β€‹αž‚αž·αžβ€‹αž˜αž½αž™β€‹αž…αŸ†αž“αž½αž“ αžαŸ’αž‰αž»αŸ†β€‹αž”αžΆαž“β€‹αžŸαž˜αŸ’αžšαŸαž…β€‹αž…αž·αžαŸ’αžβ€‹αžŸαž˜αŸ’αžšαž½αž›β€‹αžŠαŸ’αž™αžΆαž€αŸ’αžšαžΆαž˜β€‹αž€αŸ’αžšαžΆαž αŸ’αžœβ€‹αž‘αŸ…β€‹αžŠαžΌαž…β€‹αžαžΆαž„β€‹αž€αŸ’αžšαŸ„αž˜αŸ–

αž€αžΆαžšαž–αž·αžŸαŸ„αž’αž“αŸαžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αŸƒαž€αŸ’αžšαžΆαž αŸ’αžœ JanusGraph DBMS αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸƒαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αž•αŸ’αž›αžΌαžœαžŸαž˜αžšαž˜αŸ’αž™

αž€αžΆαžšαžŸαž˜αŸ’αžšαŸαž…αžαžΆαž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αžαžΆαž˜αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆαž’αž„αŸ’αž‚αž—αžΆαž–αž“αžΉαž„αž›αžΏαž“αž‡αžΆαž„αž€αžΆαžšαžŸαŸ’αžœαŸ‚αž„αžšαž€αžαžΆαž˜αž‚αŸ‚αž˜αŸ” αž‡αžΆαž›αž‘αŸ’αž’αž•αž› αžŸαŸ†αžŽαžΎαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αŸ’αžšαŸ‚αž‘αŸ…αž‡αžΆαžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ–

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

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹