เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบฅเบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบ‚เบญเบ‡ JanusGraph graph DBMS เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เปเบเป‰โ€‹เป„เบ‚โ€‹เบšเบฑเบ™โ€‹เบซเบฒโ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบŠเบญเบโ€‹เบซเบฒโ€‹เป€เบชเบฑเป‰เบ™โ€‹เบ—เบฒเบ‡โ€‹เบ—เบตเปˆโ€‹เป€เบซเบกเบฒเบฐโ€‹เบชเบปเบก

เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบฅเบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบ‚เบญเบ‡ JanusGraph graph DBMS เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เปเบเป‰โ€‹เป„เบ‚โ€‹เบšเบฑเบ™โ€‹เบซเบฒโ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบŠเบญเบโ€‹เบซเบฒโ€‹เป€เบชเบฑเป‰เบ™โ€‹เบ—เบฒเบ‡โ€‹เบ—เบตเปˆโ€‹เป€เบซเบกเบฒเบฐโ€‹เบชเบปเบก

เบชเบฐเบšเบฒเบเบ”เบตเบ—เบธเบเบ„เบปเบ™. เบžเบงเบเป€เบฎเบปเบฒเบเปเบฒเบฅเบฑเบ‡เบžเบฑเบ”เบ—เบฐเบ™เบฒเบœเบฐเบฅเบดเบ”เบ•เบฐเบžเบฑเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบเบฒเบ™เบˆเบฐเบฅเบฒเบˆเบญเบ™เบญเบญเบšเป„เบฅเบ™เปŒ. เป‚เบ„เบ‡เบเบฒเบ™เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบกเบตเบงเบฝเบเบ‡เบฒเบ™เบ—เบตเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡เบเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบชเบฐเบ–เบดเบ•เบดเบ‚เบญเบ‡เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เบ™เบฑเบเบ—เปˆเบญเบ‡เบ—เปˆเบฝเบงเปƒเบ™เบ—เบปเปˆเบงเบžเบฒเบเบžเบทเป‰เบ™.

เป€เบ›เบฑเบ™เบชเปˆเบงเบ™เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เบงเบฝเบเบ‡เบฒเบ™เบ™เบตเป‰, เบœเบนเป‰เปƒเบŠเป‰เบชเบฒเบกเบฒเบ”เบ–เบฒเบกเบ„เปเบฒเบ–เบฒเบกเบฅเบฐเบšเบปเบšเบ‚เบญเบ‡เบ›เบฐเป€เบžเบ”เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

  • เบ™เบฑเบเบ—เปˆเบญเบ‡เบ—เปˆเบฝเบงเบˆเบฒเบเป€เบ‚เบ” "A" เป„เบ›เป€เบ‚เบ” "B" เบกเบตเบˆเปเบฒเบ™เบงเบ™เป€เบ—เบปเปˆเบฒเปƒเบ”;
  • เบ™เบฑเบเบ—เปˆเบญเบ‡เบ—เปˆเบฝเบงเบœเปˆเบฒเบ™เป€เบ‚เบ” "A" เป„เบ›เบซเบฒเป€เบ‚เบ” "B" เบœเปˆเบฒเบ™เป€เบ‚เบ” "C" เปเบฅเบฐเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบœเปˆเบฒเบ™เป€เบ‚เบ” "D";
  • เบกเบฑเบ™เปƒเบŠเป‰เป€เบงเบฅเบฒเบ”เบปเบ™เบ›เบฒเบ™เปƒเบ”เบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบ—เปˆเบญเบ‡เบ—เปˆเบฝเบงเบ›เบฐเป€เบžเบ”เปƒเบ”เบ™เบถเปˆเบ‡เปƒเบ™เบเบฒเบ™เป€เบ”เบตเบ™เบ—เบฒเบ‡เบˆเบฒเบเป€เบ‚เบ” โ€œAโ€ เป„เบ›เป€เบ‚เบ” โ€œBโ€.

เปเบฅเบฐเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เบˆเปเบฒเบ™เบงเบ™เบซเบ™เบถเปˆเบ‡.

เบเบฒเบ™โ€‹เป€เบ„เบทเปˆเบญเบ™โ€‹เป„เบซเบงโ€‹เบ‚เบญเบ‡โ€‹เบœเบนเป‰โ€‹เบกเบฒโ€‹เบขเป‰เบฝเบกโ€‹เบขเบฒเบกโ€‹เปƒเบ™โ€‹เบ—เบปเปˆเบงโ€‹เบžเบทเป‰เบ™โ€‹เบ—เบตเปˆโ€‹เปเบกเปˆเบ™โ€‹เป€เบชเบฑเป‰เบ™โ€‹เบชเบฐโ€‹เปเบ”เบ‡โ€‹เบเปเบฒโ€‹เบ™เบปเบ”โ€‹. เบซเบผเบฑเบ‡เบˆเบฒเบเบญเปˆเบฒเบ™เบญเบดเบ™เป€เบ•เบตเป€เบ™เบฑเบ”, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบ„เบปเป‰เบ™เบžเบปเบšเบงเปˆเบฒ DBMSs graph เบเบฑเบ‡เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบšเบปเบ”เบฅเบฒเบเบ‡เบฒเบ™เบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐ. เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบกเบตเบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเป€เบšเบดเปˆเบ‡เบงเปˆเบฒ DBMSs เบˆเบฐเบฎเบฑเบšเบกเบทเบเบฑเบšเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเปเบ™เบงเปƒเบ” (TL; DR; เบšเปเปˆเบ”เบต).

เบ‚เป‰เบญเบเป€เบฅเบทเบญเบเปƒเบŠเป‰ DBMS JanusGraph, เป€เบ›เบฑเบ™เบ•เบปเบงเปเบ—เบ™เบ—เบตเปˆเป‚เบ”เบ”เป€เบ”เบฑเปˆเบ™เบ‚เบญเบ‡เบเบฒเบŸเปเบซเบผเปˆเบ‡เป€เบ›เบตเบ” DBMS, เป€เบŠเบดเปˆเบ‡เบญเบตเบ‡เปƒเบชเปˆเป€เบ•เบฑเบเป‚เบ™เป‚เบฅเบขเบตเบ—เบตเปˆเปƒเบซเบเปˆเบซเบผเบงเบ‡เบซเบผเบฒเบ, เป€เบŠเบดเปˆเบ‡ (เปƒเบ™เบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ) เบ„เบงเบ™เปƒเบซเป‰เบกเบฑเบ™เบกเบตเบฅเบฑเบเบชเบฐเบ™เบฐเบ›เบฐเบ•เบดเบšเบฑเบ”เบ‡เบฒเบ™เบ—เบตเปˆเป€เบซเบกเบฒเบฐเบชเบปเบก:

  • Backend เบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒ BerkeleyDB, Apache Cassandra, Scylla;
  • เบ”เบฑเบ”เบชเบฐเบ™เบตเบŠเบฑเบšเบŠเป‰เบญเบ™เบชเบฒเบกเบฒเบ”เบ–เบทเบเป€เบเบฑเบšเป„เบงเป‰เปƒเบ™ Lucene, Elasticsearch, Solr.

เบœเบนเป‰เบ‚เบฝเบ™เบ‚เบญเบ‡ JanusGraph เบ‚เบฝเบ™เบงเปˆเบฒเบกเบฑเบ™เป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบ—เบฑเบ‡ OLTP เปเบฅเบฐ OLAP.

เบ‚เป‰เบญเบเป„เบ”เป‰เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบš BerkeleyDB, Apache Cassandra, Scylla เปเบฅเบฐ ES, เปเบฅเบฐเบœเบฐเบฅเบดเบ”เบ•เบฐเบžเบฑเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบกเบฑเบเบˆเบฐเบ–เบทเบเปƒเบŠเป‰เปƒเบ™เบฅเบฐเบšเบปเบšเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เป‰เบญเบเบกเบตเบ„เบงเบฒเบกเบซเบงเบฑเบ‡เปƒเบ™เบเบฒเบ™เบ—เบปเบ”เบชเบญเบš DBMS graph เบ™เบตเป‰. เบ‚เป‰เบญเบเบžเบปเบšเบงเปˆเบฒเบกเบฑเบ™เปเบ›เบเบ—เบตเปˆเบˆเบฐเป€เบฅเบทเบญเบ BerkeleyDB เบซเบผเบฒเบเบเบงเปˆเบฒ RocksDB, เปเบ•เปˆเบ™เบฑเป‰เบ™เบญเบฒเบ”เบˆเบฐเป€เบ›เบฑเบ™เบเป‰เบญเบ™เบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบ—เบธเบฅเบฐเบเปเบฒ. เปƒเบ™เบเปเบฅเบฐเบ™เบตเปƒเบ”เบเปเปˆเบ•เบฒเบก, เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ‚เบฐเบซเบเบฒเบ, เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบœเบฐเบฅเบดเบ”เบ•เบฐเบžเบฑเบ™, เปเบ™เบฐเบ™เปเบฒเปƒเบซเป‰เปƒเบŠเป‰ backend เบเปˆเบฝเบงเบเบฑเบš Cassandra เบซเบผเบท Scylla.

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบšเปเปˆเป„เบ”เป‰เบžเบดเบˆเบฒเบฅเบฐเบ™เบฒ Neo4j เป€เบžเบฒเบฐเบงเปˆเบฒเบเบฒเบ™เบˆเบฑเบ”เบเบธเปˆเบกเบฎเบฝเบเบฎเป‰เบญเบ‡เปƒเบซเป‰เบกเบตเบชเบฐเบšเบฑเบšเบเบฒเบ™เบ„เป‰เบฒ, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบœเบฐเบฅเบดเบ”เบ•เบฐเบžเบฑเบ™เบšเปเปˆเปเบกเปˆเบ™เปเบซเบผเปˆเบ‡เป€เบ›เบตเบ”.

Graph DBMSs เป€เบงเบปเป‰เบฒเบงเปˆเบฒ: "เบ–เป‰เบฒเบกเบฑเบ™เบ„เป‰เบฒเบเบ„เบทเบเบฒเบŸ, เบ›เบฐเบ•เบดเบšเบฑเบ”เบกเบฑเบ™เบ„เบทเบเบฑเบšเบเบฒเบŸ!" - เบ„เบงเบฒเบกเบ‡เบฒเบก!

เบเปˆเบญเบ™เบญเบทเปˆเบ™ เปเบปเบ”, เบ‚เป‰เบญเบเป„เบ”เป‰เปเบ•เป‰เบกเบเบฒเบŸ, เป€เบŠเบดเปˆเบ‡เบ–เบทเบเป€เบฎเบฑเบ”เบ•เบฒเบก canons เบ‚เบญเบ‡เบเบฒเบŸ DBMSs:

เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบฅเบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบ‚เบญเบ‡ JanusGraph graph 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, เป€เบญเบปเบฒเบˆเบธเบ”เบ•เบฑเป‰เบ‡เบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเปเบ‚เบšเป„เบ›เบซเบฒเบกเบฑเบ™ (ZoneStep), เบขเบธเบ”เป‚เบ”เบเบšเปเปˆเป„เบ”เป‰เบเบฑเบšเบ„เบทเบ™เบˆเบปเบ™เบเบงเปˆเบฒเบ—เปˆเบฒเบ™เบˆเบฐเบŠเบญเบเบซเบฒ ZoneSteps เบ—เบตเปˆเบกเบตเบ‚เบญเบšเป„เบ›เบซเบฒเป€เบ‚เบ”เบ—เบตเปˆเบกเบต. ID=19, เบ™เบฑเบšเบˆเบณเบ™เบงเบ™เบ•เปˆเบญเบ‡เป‚เบชเป‰เบ”เบฑเปˆเบ‡เบเปˆเบฒเบง.

เบ‚เป‰เบฒโ€‹เบžเบฐโ€‹เป€เบˆเบปเป‰เบฒโ€‹เบšเปเปˆโ€‹เป„เบ”เป‰โ€‹เบ—เปเบฒโ€‹เบ—เปˆเบฒโ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เบฎเบนเป‰โ€‹เบˆเบฑเบ intricacies เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบŠเบญเบโ€‹เบซเบฒโ€‹เปƒเบ™โ€‹เบเบฒโ€‹เบŸโ€‹, เปเบ•เปˆโ€‹เบเบฒเบ™โ€‹เบชเบญเบšโ€‹เบ–เบฒเบกโ€‹เบ™เบตเป‰โ€‹เป„เบ”เป‰โ€‹เบ–เบทเบโ€‹เบชเป‰เบฒเบ‡โ€‹เบ‚เบถเป‰เบ™โ€‹เป‚เบ”เบโ€‹เบญเบตเบ‡โ€‹เปƒเบชเปˆโ€‹เบ›เบถเป‰เบกโ€‹เบ™เบตเป‰ (https://kelvinlawrence.net/book/Gremlin-Graph-Guide.html).

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เป‚เบซเบฅเบ” 50 เบžเบฑเบ™เป€เบžเบ‡เบ•เบฑเป‰เบ‡เปเบ•เปˆ 3 เบซเบฒ 20 เบˆเบธเบ”เปƒเบ™เบ„เบงเบฒเบกเบเบฒเบงเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™ JanusGraph เป‚เบ”เบเปƒเบŠเป‰ backend BerkeleyDB, เบชเป‰เบฒเบ‡เบ”เบฑเบ”เบชเบฐเบ™เบตเบญเบตเบ‡เบ•เบฒเบกเบเบฒเบ™ เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบœเบนเป‰เบ™เปเบฒ.

script เบ”เบฒเบงเป‚เบซเบผเบ” 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 เปเบฅเบฐ RAM 16 GB เปƒเบ™ SSD. JanusGraph เบ–เบทเบเบ™เบณเปƒเบŠเป‰เป‚เบ”เบเปƒเบŠเป‰เบ„เบณเบชเบฑเปˆเบ‡เบ™เบตเป‰:

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

เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰, เบ‚เปเป‰เบกเบนเบ™เปเบฅเบฐเบ”เบฑเบ”เบชเบฐเบ™เบตเบ—เบตเปˆเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ„เบปเป‰เบ™เบซเบฒเบเบปเบ‡เบเบฑเบ™เบ—เบตเปˆเปเบ™เปˆเบ™เบญเบ™เบˆเบฐเบ–เบทเบเป€เบเบฑเบšเป„เบงเป‰เปƒเบ™ BerkeleyDB. เป‚เบ”เบเป„เบ”เป‰เบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเบ—เบตเปˆเปƒเบซเป‰เบเปˆเบญเบ™เบซเบ™เป‰เบฒเบ™เบตเป‰, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบฎเบฑเบšเป€เบงเบฅเบฒเป€เบ—เบปเปˆเบฒเบเบฑเบšเบซเบผเบฒเบเบชเบดเบšเบงเบดเบ™เบฒเบ—เบต.

เป‚เบ”เบเบเบฒเบ™เปเบฅเปˆเบ™ 4 scripts เบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡เปƒเบ™เบ‚เบฐเบซเบ™เบฒเบ™, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบˆเบฑเบ”เบเบฒเบ™เบ›เปˆเบฝเบ™ DBMS เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบœเบฑเบเบ—เบตเปˆเบกเบตเบ™เป‰เปเบฒ Java stacktraces เบ—เบตเปˆเบกเบตเบ„เบงเบฒเบกเบชเบธเบ (เปเบฅเบฐเบžเบงเบเป€เบฎเบปเบฒเบ—เบธเบเบ„เบปเบ™เบกเบฑเบเบญเปˆเบฒเบ™ Java stacktraces) เปƒเบ™เบšเบฑเบ™เบ—เบถเบ Docker.

เบซเบผเบฑเบ‡เบˆเบฒเบเบ—เบตเปˆเบ„เบดเบ”เบšเบฒเบ‡เบญเบฑเบ™, เบ‚เป‰เบญเบเป„เบ”เป‰เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเป€เบฎเบฑเบ”เปเบœเบ™เบงเบฒเบ”เบเบฃเบฒเบšเปƒเบซเป‰เบ‡เปˆเบฒเบเบ•เปเปˆเบชเบดเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบฅเบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เบปเบ”โ€‹เบชเบญเบšโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบ‚เบญเบ‡ JanusGraph graph 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 เบ‚เบญเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡, เป€เบŠเบดเปˆเบ‡เบšเปเปˆเป„เบ”เป‰เบ”เบปเบ™เปƒเบˆเปƒเบ™เปเบ‡เปˆเบ”เบตเปƒเบ™เปเบ‡เปˆเบ‚เบญเบ‡เบ„เบงเบฒเบกเบชเบฐเบซเบ‡เปˆเบฒเบ‡เบฒเบก, เปเบ•เปˆเบญเบฒเบ”เบˆเบฐเป€เบ›เบฑเบ™เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเป€เบฎเบฑเบ”เบงเบฝเบเป„เบ”เป‰เบขเปˆเบฒเบ‡เบชเบปเบกเบšเบนเบ™เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”.

เป‚เบ„เบ‡เบเบฒเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ Apache ClickHouse เปเบฅเป‰เบง, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เป‰เบญเบเบˆเบถเปˆเบ‡เบ•เบฑเบ”เบชเบดเบ™เปƒเบˆเบ—เบปเบ”เบชเบญเบšเบเบฒเบ™เบ„เบปเป‰เบ™เบ„เบงเป‰เบฒเบ‚เบญเบ‡เบ‚เป‰เบญเบเบเปˆเบฝเบงเบเบฑเบš DBMS เบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ™เบตเป‰.

เบ™เบณเปƒเบŠเป‰ ClickHouse เป‚เบ”เบเปƒเบŠเป‰เบชเบนเบ”เบ‡เปˆเบฒเบเป†:

sudo docker run -d --name clickhouse_1 
     --ulimit nofile=262144:262144 
     -v /opt/clickhouse/log:/var/log/clickhouse-server 
     -v /opt/clickhouse/data:/var/lib/clickhouse 
     yandex/clickhouse-server

เบ‚เป‰เบญเบเบชเป‰เบฒเบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบฅเบฐเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปƒเบ™เบกเบฑเบ™เป€เบŠเบฑเปˆเบ™เบ™เบตเป‰:

CREATE TABLE 
db.steps (`area` Int64, `when` DateTime64(1, 'Europe/Moscow') DEFAULT now64(), `zone` Int64, `person` Int64) 
ENGINE = MergeTree() ORDER BY (area, zone, person) SETTINGS index_granularity = 8192

เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเป„เบ”เป‰เบ•เบทเปˆเบกเบ‚เปเป‰เบกเบนเบ™เปƒเบชเปˆเบกเบฑเบ™เป‚เบ”เบเปƒเบŠเป‰ script เบ•เปเปˆเป„เบ›เบ™เบตเป‰:

from time import time

from clickhouse_driver import Client
from random import random

client = Client('vm-12c2c34c-df68-4a98-b1e5-a4d1cef1acff.domain',
                database='db',
                password='secret')

max = 20

for r in range(0, 100000):

    if r % 1000 == 0:
        print("CNT: {}, TS: {}".format(r, time()))

    data = [{
            'area': 0,
            'zone': 0,
            'person': r
        }]

    while True:
        if random() < 0.3:
            break

        data.append({
                'area': 0,
                'zone': int(random() * (max - 2)) + 1,
                'person': r
            })

    data.append({
            'area': 0,
            'zone': max - 1,
            'person': r
        })

    client.execute(
        'INSERT INTO steps (area, zone, person) VALUES',
        data
    )

เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆ inserts เป€เบ‚เบปเป‰เบฒเบกเบฒเปƒเบ™ batches, เบเบฒเบ™เบ•เบทเปˆเบกเบ‚เปเป‰เบกเบนเบ™เปเบกเปˆเบ™เป„เบงเบเบงเปˆเบฒ 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 เบงเบดเบ™เบฒเบ—เบต. เบ™เบตเป‰เปเบกเปˆเบ™เบ•เบปเบงเบขเปˆเบฒเบ‡เบ‚เบญเบ‡เป€เบงเบฅเบฒเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบฑเบš(*) เบœเปˆเบฒเบ™ 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. เบ•เบปเบงเบขเปˆเบฒเบ‡, เบเบฒเบ™เบชเป‰เบฒเบ‡เบ”เบฑเบ”เบชเบฐเบ™เบตเบ•เป‰เบญเบ‡เป€เบฎเบฑเบ”เป‚เบ”เบเบเบฒเบ™เบ‚เบฝเบ™เบฅเบฐเบซเบฑเบ”เปƒเบ™ console 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()

เบ‚เป‰เบญเบเบšเปเปˆเบชเบฒเบกเบฒเบ”เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบ—เบตเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ•เบดเบžเบฒเบšเป‚เบ”เบเปƒเบŠเป‰เป€เบงเบฅเบฒเบ›เบฐเบกเบงเบ™เบœเบปเบ™เบซเบ™เป‰เบญเบเบเบงเปˆเบฒเบซเบ™เบถเปˆเบ‡เบงเบดเบ™เบฒเบ—เบต.

เบชเบปเบกเบšเบฑเบ”เบชเบดเบ™เบ—เปเบฒเบ‚เบญเบ‡เป€เบฅเบทเปˆเบญเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบ„เบงเบฒเบกเบ„เบดเบ”เบ—เบตเปˆเบชเบงเบเบ‡เบฒเบกเปเบฅเบฐเบเบฒเบ™เบชเป‰เบฒเบ‡เปเบšเบšเบˆเปเบฒเบฅเบญเบ‡เปเบšเบš paradigmatic เบšเปเปˆเป„เบ”เป‰เบ™เปเบฒเป„เบ›เบชเบนเปˆเบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบ—เบตเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™, เป€เบŠเบดเปˆเบ‡เบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เป€เบ–เบดเบ‡เบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบชเบนเบ‡เบเบงเปˆเบฒเบซเบผเบฒเบเป‚เบ”เบเปƒเบŠเป‰เบ•เบปเบงเบขเปˆเบฒเบ‡เบ‚เบญเบ‡ ClickHouse. เบเปเบฅเบฐเบ™เบตเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบ—เบตเปˆเบ™เปเบฒเบชเบฐเป€เบซเบ™เบตเปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰เปเบกเปˆเบ™เป€เบ›เบฑเบ™เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบ•เปเปˆเบ•เป‰เบฒเบ™เบ—เบตเปˆเบŠเบฑเบ”เป€เบˆเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบŸ DBMSs, เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบกเบฑเบ™เป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเป€เบซเบกเบฒเบฐเบชเบปเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบชเป‰เบฒเบ‡เปเบšเบšเบˆเปเบฒเบฅเบญเบ‡เปƒเบ™เบ„เปเบฒเบ‚เบงเบฑเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ.

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™