เด…เดจเตเดฏเต‹เดœเตเดฏเดฎเดพเดฏ เดชเดพเดคเด•เตพ เด•เดฃเตเดŸเต†เดคเตเดคเตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เดชเตเดฐเดถเตเดจเด‚ เดชเดฐเดฟเดนเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเดฏเดฟ JanusGraph เด—เตเดฐเดพเดซเต DBMS-เดจเตเดฑเต† เดชเตเดฐเดฏเต‹เด—เด•เตเดทเดฎเดค เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจ เด’เดฐเต เดชเดฐเต€เด•เตเดทเดฃเด‚

เด…เดจเตเดฏเต‹เดœเตเดฏเดฎเดพเดฏ เดชเดพเดคเด•เตพ เด•เดฃเตเดŸเต†เดคเตเดคเตเดจเตเดจเดคเดฟเดจเตเดณเตเดณ เดชเตเดฐเดถเตเดจเด‚ เดชเดฐเดฟเดนเดฐเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเดพเดฏเดฟ JanusGraph เด—เตเดฐเดพเดซเต DBMS-เดจเตเดฑเต† เดชเตเดฐเดฏเต‹เด—เด•เตเดทเดฎเดค เดชเดฐเดฟเดถเต‹เดงเดฟเด•เตเด•เตเดจเตเดจ เด’เดฐเต เดชเดฐเต€เด•เตเดทเดฃเด‚

เดŽเดฒเตเดฒเดพเดตเตผเด•เตเด•เตเด‚ เดนเดพเดฏเต. เด“เดซเตโ€Œเดฒเตˆเตป เดŸเตเดฐเดพเดซเดฟเด•เต เดตเดฟเดถเด•เดฒเดจเดคเตเดคเดฟเดจเดพเดฏเดฟ เดžเด™เตเด™เตพ เด’เดฐเต เด‰เตฝเดชเตเดชเดจเตเดจเด‚ เดตเดฟเด•เดธเดฟเดชเตเดชเดฟเด•เตเด•เตเด•เดฏเดพเดฃเต. เดชเตเดฐเดฆเต‡เดถเด™เตเด™เดณเดฟเดฒเตเดŸเดจเต€เดณเดฎเตเดณเตเดณ เดธเดจเตเดฆเตผเดถเด• เดฑเต‚เดŸเตเดŸเตเด•เดณเตเดŸเต† เดธเตเดฅเดฟเดคเดฟเดตเดฟเดตเดฐ เดตเดฟเดถเด•เดฒเดจเดตเตเดฎเดพเดฏเดฟ เดฌเดจเตเดงเดชเตเดชเต†เดŸเตเดŸ เด’เดฐเต เดŸเดพเดธเตโ€Œเด•เต เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเดฟเดจเตเดฃเตเดŸเต.

เดˆ เดŸเดพเดธเตเด•เตเด•เดฟเดจเตเดฑเต† เดญเดพเด—เดฎเดพเดฏเดฟ, เด‰เดชเดฏเต‹เด•เตเดคเดพเด•เตเด•เตพเด•เตเด•เต เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจ เดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ เดธเดฟเดธเตเดฑเตเดฑเด‚ เดšเต‹เดฆเตเดฏเด™เตเด™เตพ เดšเต‹เดฆเดฟเด•เตเด•เดพเตป เด•เดดเดฟเดฏเตเด‚:

  • "เดŽ" เดเดฐเดฟเดฏเดฏเดฟเตฝ เดจเดฟเดจเตเดจเต "เดฌเดฟ" เดเดฐเดฟเดฏเดฏเดฟเดฒเต‡เด•เตเด•เต เดŽเดคเตเดฐ เดธเดจเตเดฆเตผเดถเด•เตผ เด•เดŸเดจเตเดจเตเดชเต‹เดฏเดฟ;
  • "เดŽ" เดเดฐเดฟเดฏเดฏเดฟเตฝ เดจเดฟเดจเตเดจเต "เดฌเดฟ" เดเดฐเดฟเดฏเดฏเดฟเดฒเต‡เด•เตเด•เต "เดธเดฟ" เดเดฐเดฟเดฏเดฏเดฟเดฒเต‚เดŸเต†เดฏเตเด‚ เดคเตเดŸเตผเดจเตเดจเต "เดกเดฟ" เดเดฐเดฟเดฏเดฏเดฟเดฒเต‚เดŸเต†เดฏเตเด‚ เดŽเดคเตเดฐ เดธเดจเตเดฆเตผเดถเด•เตผ เด•เดŸเดจเตเดจเตเดชเต‹เดฏเดฟ;
  • เด’เดฐเต เดชเตเดฐเดคเตเดฏเต‡เด• เดคเดฐเด‚ เดธเดจเตเดฆเตผเดถเด•เตผเด•เตเด•เต "A" เดเดฐเดฟเดฏเดฏเดฟเตฝ เดจเดฟเดจเตเดจเต "B" เดเดฐเดฟเดฏเดฏเดฟเดฒเต‡เด•เตเด•เต เดฏเดพเดคเตเดฐ เดšเต†เดฏเตเดฏเดพเตป เดŽเดคเตเดฐ เดธเดฎเดฏเดฎเต†เดŸเตเดคเตเดคเต.

เดธเดฎเดพเดจเดฎเดพเดฏ เด…เดจเดฒเดฟเดฑเตเดฑเดฟเด•เตเด•เตฝ เดšเต‹เดฆเตเดฏเด™เตเด™เดณเตเด‚.

เดชเตเดฐเดฆเต‡เดถเด™เตเด™เดณเดฟเดฒเตเดŸเดจเต€เดณเด‚ เดธเดจเตเดฆเตผเดถเด•เดฐเตเดŸเต† เดšเดฒเดจเด‚ เด’เดฐเต เดกเดฏเดฑเด•เตเดŸเต เด—เตเดฐเดพเดซเต เด†เดฃเต. เด‡เดจเตเดฑเตผเดจเต†เดฑเตเดฑเต เดตเดพเดฏเดฟเดšเตเดšเดคเดฟเดจเตเดถเต‡เดทเด‚, เด—เตเดฐเดพเดซเต เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเตเด•เดณเตเด‚ เดตเดฟเดถเด•เดฒเดจ เดฑเดฟเดชเตเดชเต‹เตผเดŸเตเดŸเตเด•เตพเด•เตเด•เดพเดฏเดฟ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเตเดฃเตเดŸเต†เดจเตเดจเต เดžเดพเตป เด•เดฃเตเดŸเต†เดคเตเดคเดฟ. เด‡เดคเตเดคเดฐเด‚ เดšเต‹เดฆเตเดฏเด™เตเด™เดณเต† เด—เตเดฐเดพเดซเต เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเตเด•เตพ เดŽเด™เตเด™เดจเต† เดจเต‡เดฐเดฟเดŸเตเดฎเต†เดจเตเดจเต เด•เดพเดฃเดพเตป เดŽเดจเดฟเด•เตเด•เต เด†เด—เตเดฐเดนเดฎเตเดฃเตเดŸเดพเดฏเดฟเดฐเตเดจเตเดจเต (TL; DR; เดฎเต‹เดถเดฎเดพเดฏเดฟ).

เดžเดพเตป DBMS เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเตป เดคเดฟเดฐเดžเตเดžเต†เดŸเตเดคเตเดคเต เดœเดพเดจเดธเต เด—เตเดฐเดพเดซเต, เด—เตเดฐเดพเดซเต เด“เดชเตเดชเตบ เดธเต‹เดดเตโ€Œเดธเต เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเดฟเดจเตเดฑเต† เดฎเดฟเด•เดšเตเดš เดชเตเดฐเดคเดฟเดจเดฟเดงเดฟ เดŽเดจเตเดจ เดจเดฟเดฒเดฏเดฟเตฝ, เด…เดคเต (เดŽเดจเตเดฑเต† เด…เดญเดฟเดชเตเดฐเดพเดฏเดคเตเดคเดฟเตฝ) เดฎเดพเดจเตเดฏเดฎเดพเดฏ เดชเตเดฐเดตเตผเดคเตเดคเดจ เดธเดตเดฟเดถเต‡เดทเดคเด•เตพ เดจเตฝเด•เต‡เดฃเตเดŸ, เดฎเตเดคเดฟเตผเดจเตเดจ เดธเดพเด™เตเด•เต‡เดคเดฟเด•เดตเดฟเดฆเตเดฏเด•เดณเตเดŸเต† เด’เดฐเต เด•เต‚เดŸเตเดŸเดคเตเดคเต† เด†เดถเตเดฐเดฏเดฟเด•เตเด•เตเดจเตเดจเต:

  • เดฌเต†เตผเด•เตเด•เตโ€Œเดฒเดฟเดกเดฟเดฌเดฟ เดธเตเดฑเตเดฑเต‹เดฑเต‡เดœเต เดฌเดพเด•เตเด•เต†เตปเดกเต, เด…เดชเตเดชเดพเดšเตเดšเต† เด•เดธเดพเดจเตเดฆเตเดฐ, เดธเตเด•เดฟเดฒเตเดฒ;
  • เดธเด™เตเด•เต€เตผเดฃเตเดฃเดฎเดพเดฏ เดธเต‚เดšเดฟเด•เด•เตพ Lucene, Elasticsearch, Solr เดŽเดจเตเดจเดฟเดตเดฏเดฟเตฝ เดธเต‚เด•เตเดทเดฟเด•เตเด•เดพเด‚.

OLTP, OLAP เดŽเดจเตเดจเดฟเดตเดฏเตโ€Œเด•เตเด•เต เด‡เดคเต เด…เดจเตเดฏเต‹เดœเตเดฏเดฎเดพเดฃเต†เดจเตเดจเต JanusGraph-เดจเตเดฑเต† เดฐเดšเดฏเดฟเดคเดพเด•เตเด•เตพ เดŽเดดเตเดคเตเดจเตเดจเต.

เดžเดพเตป BerkeleyDB, Apache Cassandra, Scylla, ES เดŽเดจเตเดจเดฟเดตเดฏเตโ€Œเด•เตเด•เตŠเดชเตเดชเด‚ เดชเตเดฐเดตเตผเดคเตเดคเดฟเดšเตเดšเดฟเดŸเตเดŸเตเดฃเตเดŸเต, เดˆ เด‰เตฝเดชเตเดชเดจเตเดจเด™เตเด™เตพ เดžเด™เตเด™เดณเตเดŸเต† เดธเดฟเดธเตเดฑเตเดฑเด™เตเด™เดณเดฟเตฝ เดชเดฒเดชเตเดชเต‹เดดเตเด‚ เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเดฑเตเดฃเตเดŸเต, เด…เดคเดฟเดจเดพเตฝ เดˆ เด—เตเดฐเดพเดซเต DBMS เดชเดฐเต€เด•เตเดทเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเตฝ เดŽเดจเดฟเด•เตเด•เต เดถเตเดญเดพเดชเตเดคเดฟ เดตเดฟเดถเตเดตเดพเดธเดฎเตเดฃเตเดŸเดพเดฏเดฟเดฐเตเดจเตเดจเต. RocksDB-เดฏเต†เด•เตเด•เดพเตพ BerkeleyDB เดคเดฟเดฐเดžเตเดžเต†เดŸเตเด•เตเด•เตเดจเตเดจเดคเต เดตเดฟเดšเดฟเดคเตเดฐเดฎเดพเดฃเต†เดจเตเดจเต เดžเดพเตป เด•เดฃเตเดŸเต†เดคเตเดคเดฟ, เดชเด•เตเดทเต‡ เด…เดคเต เด‡เดŸเดชเดพเดŸเต เด†เดตเดถเตเดฏเด•เดคเด•เตพ เด•เดพเดฐเดฃเดฎเดพเดฏเดฟเดฐเดฟเด•เตเด•เดพเด‚. เดเดคเต เดธเดพเดนเดšเดฐเตเดฏเดคเตเดคเดฟเดฒเตเด‚, เดธเตเด•เต†เดฏเดฟเดฒเดฌเดฟเตพ, เด‰เตฝเดชเตเดชเดจเตเดจ เด‰เดชเดฏเต‹เด—เดคเตเดคเดฟเดจเต, เด•เดธเดพเดจเตเดฆเตเดฐเดฏเดฟเดฒเต‹ เดธเตเด•เดฟเดฒเตเดฒเดฏเดฟเดฒเต‹ เด’เดฐเต เดฌเดพเด•เตเด•เต†เตปเดกเต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เดพเตป เดจเดฟเตผเดฆเตเดฆเต‡เดถเดฟเด•เตเด•เตเดจเตเดจเต.

เดžเดพเตป Neo4j เดชเดฐเดฟเด—เดฃเดฟเดšเตเดšเดฟเดฒเตเดฒ, เด•เดพเดฐเดฃเด‚ เด•เตเดฒเดธเตเดฑเตเดฑเดฑเดฟเด™เตเด™เดฟเดจเต เด’เดฐเต เดตเดพเดฃเดฟเดœเตเดฏ เดชเดคเดฟเดชเตเดชเต เด†เดตเดถเตเดฏเดฎเดพเดฃเต, เด…เดคเดพเดฏเดคเต เด‰เตฝเดชเตเดชเดจเตเดจเด‚ เด“เดชเตเดชเตบ เดธเต‹เดดเตโ€Œเดธเต เด…เดฒเตเดฒ.

เด—เตเดฐเดพเดซเต 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()

เดฑเดทเตเดฏเตป เดญเดพเดทเดฏเดฟเตฝ เด‡เดคเตเดชเต‹เดฒเต†เดฏเดพเดฃเต: ID=0 เด‰เดณเตเดณ เด’เดฐเต เดธเต‹เตบ เด•เดฃเตเดŸเต†เดคเตเดคเตเด•, เด…เดคเดฟเดฒเต‡เด•เตเด•เต เด’เดฐเต เดŽเดกเตเดœเต เดชเต‹เด•เตเดจเตเดจ เดŽเดฒเตเดฒเดพ เดถเต€เตผเดทเด•เด™เตเด™เดณเตเด‚ เดŽเดŸเตเด•เตเด•เตเด• (ZoneStep), เดธเต‹เดฃเดฟเดฒเต‡เด•เตเด•เต เด’เดฐเต เดŽเดกเตเดœเต เด‰เดณเตเดณ เด† เดธเต‹เตบเดธเตเดฑเตเดฑเต†เดชเตเดชเตเด•เตพ เด•เดฃเตเดŸเต†เดคเตเดคเตเดจเตเดจเดคเต เดตเดฐเต† เดชเดฟเดจเตเดจเต‹เดŸเตเดŸเต เดชเต‹เด•เดพเดคเต† เดธเตเดฑเตเดฑเต‹เดฎเตเดชเต เดšเต†เดฏเตเดฏเตเด• เดเดกเดฟ=19, เด…เดคเตเดคเดฐเด‚ เดšเต†เดฏเดฟเดจเตเด•เดณเตเดŸเต† เดŽเดฃเตเดฃเด‚ เดŽเดฃเตเดฃเตเด•.

เด—เตเดฐเดพเดซเตเด•เดณเดฟเตฝ เดคเดฟเดฐเดฏเตเดจเตเดจเดคเดฟเดจเตเดฑเต† เดŽเดฒเตเดฒเดพ เดธเด™เตเด•เต€เตผเดฃเดคเด•เดณเตเด‚ เดžเดพเตป เด…เดฑเดฟเดฏเตเดจเตเดจเดคเดพเดฏเดฟ เดจเดŸเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ, เดชเด•เตเดทเต‡ เดˆ เดชเตเดธเตเดคเด•เดคเตเดคเต† เด…เดŸเดฟเดธเตเดฅเดพเดจเดฎเดพเด•เตเด•เดฟเดฏเดพเดฃเต เดˆ เดšเต‹เดฆเตเดฏเด‚ เดธเตƒเดทเตเดŸเดฟเดšเตเดšเดคเต (https://kelvinlawrence.net/book/Gremlin-Graph-Guide.html).

เดฌเต†เตผเด•เตเด•เตโ€Œเดฒเดฟเดกเดฟเดฌเดฟ เดฌเดพเด•เตเด•เต†เตปเดกเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต 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 เดฑเดพเดฎเตเด‚ เด‰เดณเตเดณ VM เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต. เดˆ เด•เดฎเดพเตปเดกเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเดพเดฃเต 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()

เดฑเดทเตเดฏเตป เดญเดพเดทเดฏเดฟเตฝ เด‡เดคเตเดชเต‹เดฒเต†เดฏเดพเดฃเต: ID=0 เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต ZoneStep เด•เดฃเตเดŸเต†เดคเตเดคเตเด•, ID=19 เด‰เดณเตเดณ ZoneStep เด•เดฃเตเดŸเต†เดคเตเดคเตเดจเตเดจเดคเตเดตเดฐเต† เดคเดฟเดฐเดฟเด•เต† เดชเต‹เด•เดพเดคเต† เดธเตโ€Œเดฑเตเดฑเต‹เดฎเตเดชเต เดšเต†เดฏเตเดฏเตเด•, เด…เดคเตเดคเดฐเด‚ เดšเต†เดฏเดฟเดจเตเด•เดณเตเดŸเต† เดŽเดฃเตเดฃเด‚ เดŽเดฃเตเดฃเตเด•.

เด…เดจเดพเดตเดถเตเดฏ เด•เดฃเด•เตเดทเดจเตเด•เตพ เดธเตƒเดทเตเดŸเดฟเด•เตเด•เดพเดคเดฟเดฐเดฟเด•เตเด•เดพเตป, เด†เดŸเตเดฐเดฟเดฌเตเดฏเต‚เดŸเตเดŸเตเด•เดณเดฟเดฒเต‡เด•เตเด•เต เดŽเดจเตเดจเต†เดคเตเดคเดจเตเดจเต† เดชเดฐเดฟเดฎเดฟเดคเดชเตเดชเต†เดŸเตเดคเตเดคเตเดจเตเดจเดคเดฟเดจเต เดฎเตเด•เดณเดฟเตฝ เดจเตฝเด•เดฟเดฏเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจ เดฒเต‹เดกเดฟเด‚เด—เต เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเตเด‚ เดžเดพเตป เดฒเดณเดฟเดคเดฎเดพเด•เตเด•เดฟ.

เด…เดญเตเดฏเตผเดคเตเดฅเดจ เดชเต‚เตผเดคเตเดคเดฟเดฏเดพเด•เดพเตป เด‡เดจเดฟเดฏเตเด‚ เด•เตเดฑเดšเตเดšเต เดธเต†เด•เตเด•เดจเตเดฑเตเด•เตพ เดŽเดŸเตเดคเตเดคเต, เด‡เดคเต เดžเด™เตเด™เดณเตเดŸเต† เดŸเดพเดธเตโ€Œเด•เตเด•เดฟเดจเต เดชเต‚เตผเดฃเตเดฃเดฎเดพเดฏเตเด‚ เด…เดธเตเดตเต€เด•เดพเดฐเตเดฏเดฎเดพเดฏเดฟเดฐเตเดจเตเดจเต, เด•เดพเดฐเดฃเด‚ เด‡เดคเต เดเดคเต†เด™เตเด•เดฟเดฒเตเด‚ เดคเดฐเดคเตเดคเดฟเดฒเตเดณเตเดณ AdHoc เด…เดญเตเดฏเตผเดคเตเดฅเดจเด•เดณเตเดŸเต† เด†เดตเดถเตเดฏเด™เตเด™เตพเด•เตเด•เต เด’เดŸเตเดŸเตเด‚ เด…เดจเตเดฏเต‹เดœเตเดฏเดฎเดฒเตเดฒ.

เดžเดพเตป เดธเตเด•เดฟเดฒเตเดฒ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดœเดพเดจเดธเตเด—เตเดฐเดพเดซเต เดตเดฟเดจเตเดฏเดธเดฟเด•เตเด•เดพเตป เดถเตเดฐเดฎเดฟเดšเตเดšเต, เดŽเดจเตเดจเดพเตฝ เด‡เดคเตเด‚ เด•เดพเดฐเตเดฏเดฎเดพเดฏ เดชเตเดฐเด•เดŸเดจ เดฎเดพเดฑเตเดฑเด™เตเด™เดณเตŠเดจเตเดจเตเด‚ เดตเดฐเตเดคเตเดคเดฟเดฏเดฟเดฒเตเดฒ.

"เด‡เดคเต เด’เดฐเต เด—เตเดฐเดพเดซเต เดชเต‹เดฒเต† เดคเต‹เดจเตเดจเตเดจเตเดจเต" เดŽเดจเตเดจ เดตเดธเตเดคเตเดค เด‰เดฃเตเดŸเดพเดฏเดฟเดฐเตเดจเตเดจเดฟเดŸเตเดŸเตเด‚, เด…เดคเต เดตเต‡เด—เดคเตเดคเดฟเตฝ เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเดพเตป เดŽเดจเดฟเด•เตเด•เต เด—เตเดฐเดพเดซเต DBMS เดฒเดญเดฟเด•เตเด•เดฟเดฒเตเดฒ. เดŽเดจเดฟเด•เตเด•เต เดŽเดจเตเดคเต†เด™เตเด•เดฟเดฒเตเด‚ เด…เดฑเดฟเดฏเดฟเดฒเตเดฒเต†เดจเตเดจเตเด‚ เด’เดฐเต เดจเดฟเดฎเดฟเดทเดคเตเดคเดฟเดจเตเดณเตเดณเดฟเตฝ เดˆ เดคเดฟเดฐเดฏเตฝ เดจเดŸเดคเตเดคเดพเตป JanusGraph-เดจเต† เดชเตเดฐเต‡เดฐเดฟเดชเตเดชเดฟเด•เตเด•เดพเตป เด•เดดเดฟเดฏเตเดฎเต†เดจเตเดจเตเด‚ เดžเดพเตป เดชเต‚เตผเดฃเตเดฃเดฎเดพเดฏเตเด‚ เด…เดจเตเดฎเดพเดจเดฟเด•เตเด•เตเดจเตเดจเต, เดŽเดจเตเดจเดฟเดฐเตเดจเตเดจเดพเดฒเตเด‚, เดŽเดจเดฟเด•เตเด•เต เด…เดคเต เดšเต†เดฏเตเดฏเดพเตป เด•เดดเดฟเดžเตเดžเดฟเดฒเตเดฒ.

เดชเตเดฐเดถเตเดจเด‚ เด‡เดชเตเดชเต‹เดดเตเด‚ เดชเดฐเดฟเดนเดฐเดฟเด•เตเด•เต‡เดฃเตเดŸเดคเดฟเดจเดพเตฝ, เดžเดพเตป เดœเต‹เดฏเดฟเดจเตเด•เดณเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเตเด‚ เดชเดŸเตเดŸเดฟเด•เด•เดณเตเดŸเต† เดชเดฟเดตเดฑเตเดฑเตเด•เดณเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเตเด‚ เดšเดฟเดจเตเดคเดฟเด•เตเด•เดพเตป เดคเตเดŸเด™เตเด™เดฟ, เด…เดคเต เดšเดพเดฐเตเดคเดฏเตเดŸเต† เด•เดพเดฐเตเดฏเดคเตเดคเดฟเตฝ เดถเตเดญเดพเดชเตเดคเดฟเดตเดฟเดถเตเดตเดพเดธเดคเตเดคเต† เดชเตเดฐเดšเต‹เดฆเดฟเดชเตเดชเดฟเด•เตเด•เตเดจเตเดจเดฟเดฒเตเดฒ, เดชเด•เตเดทเต‡ เดชเตเดฐเดพเดฏเต‹เด—เดฟเด•เดฎเดพเดฏเดฟ เดชเต‚เตผเดฃเตเดฃเดฎเดพเดฏเตเด‚ เดชเตเดฐเดตเตผเดคเตเดคเดจเด•เตเดทเดฎเดฎเดพเดฏ เด“เดชเตเดทเดจเดพเดฏเดฟเดฐเดฟเด•เตเด•เดพเด‚.

เดžเด™เตเด™เดณเตเดŸเต† เดชเตเดฐเต‹เดœเด•เตเดฑเตเดฑเต เด‡เดคเดฟเดจเด•เด‚ เดคเดจเตเดจเต† เด…เดชเตเดชเดพเดšเตเดšเต† เด•เตเดฒเดฟเด•เตเด•เตเดนเต—เดธเต เด‰เดชเดฏเต‹เด—เดฟเด•เตเด•เตเดจเตเดจเต, เด…เดคเดฟเดจเดพเตฝ เดˆ เด…เดจเดฒเดฟเดฑเตเดฑเดฟเด•เตเด•เตฝ เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเดฟเตฝ เดŽเดจเตเดฑเต† เด—เดตเต‡เดทเดฃเด‚ เดชเดฐเต€เด•เตเดทเดฟเด•เตเด•เดพเตป เดžเดพเตป เดคเต€เดฐเตเดฎเดพเดจเดฟเดšเตเดšเต.

เด’เดฐเต เดฒเดณเดฟเดคเดฎเดพเดฏ เดชเดพเดšเด•เด•เตเด•เตเดฑเดฟเดชเตเดชเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต 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

เด‡เดจเดฟเดชเตเดชเดฑเดฏเตเดจเตเดจ เดธเตเด•เตเดฐเดฟเดชเตเดฑเตเดฑเต เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดžเดพเตป เด…เดคเต เดกเดพเดฑเตเดฑ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดชเต‚เดฐเดฟเดชเตเดชเดฟเดšเตเดšเต:

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
    )

เด‰เตพเดชเตเดชเต†เดŸเตเดคเตเดคเดฒเตเด•เตพ เดฌเดพเดšเตเดšเตเด•เดณเดพเดฏเดฟ เดตเดฐเตเดจเตเดจเดคเดฟเดจเดพเตฝ, เดชเต‚เดฐเดฟเดชเตเดชเดฟเด•เตเด•เตฝ เดœเดพเดจเดธเต เด—เตเดฐเดพเดซเดฟเดจเต‡เด•เตเด•เดพเตพ เดตเดณเดฐเต† เดตเต‡เด—เดคเตเดคเดฟเดฒเดพเดฏเดฟเดฐเตเดจเตเดจเต.

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-เดฒเต‡เด•เตเด•เต เดฒเต‹เดกเตเดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเต เดฎเตเดฎเตเดชเต, Apache Flink เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เด‡เดตเดจเตเดฑเต เดธเตเดŸเตเดฐเต€เด‚ เดชเตเดฐเต€-เดชเตเดฐเต‹เดธเดธเตเดธเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดฒเต‚เดŸเต†, เดฎเต†เดฑเตเดฑเต€เดฐเดฟเดฏเดฒเตˆเดธเตเดกเต เด•เดพเดดเตโ€Œเดšเด•เดณเตเด‚ เดธเดฎเดพเดจเตเดคเดฐเดตเตฝเด•เตเด•เดฐเดฃเดตเตเด‚ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดšเต‹เดฆเตเดฏเด™เตเด™เตพ เด•เต‚เดŸเตเดคเตฝ เด’เดชเตเดฑเตเดฑเดฟเดฎเตˆเดธเต เดšเต†เดฏเตเดฏเดพเดจเดพเด•เตเด‚.

เดชเตเดฐเด•เดŸเดจเด‚ เดตเดณเดฐเต† เดฎเดฟเด•เดšเตเดšเดคเดพเดฃเต, เดŸเต‡เดฌเดฟเดณเตเด•เตพ เดชเตเดฐเต‹เด—เตเดฐเดพเดฎเดพเดฑเตเดฑเดฟเด•เต เด†เดฏเดฟ เดชเดฟเดตเดฑเตเดฑเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดจเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เดจเดฎเตเด•เตเด•เต เดšเดฟเดจเตเดคเดฟเด•เตเด•เต‡เดฃเตเดŸเดฟ เดตเดฐเดฟเดฒเตเดฒ. เดฎเตเดฎเตเดชเต, เด…เดชเตเดชเดพเดšเตเดšเต† เดชเดพเตผเด•เตเด•เตเดตเต†เดฑเตเดฑเดฟเดฒเต‡เด•เตเด•เต เด…เดชเตโ€Œเดฒเต‹เดกเต เดšเต†เดฏเตเดฏเตเดจเตเดจเดคเดฟเดฒเต‚เดŸเต† เดตเต†เตผเดŸเตเดŸเดฟเด•เตเด•เดฏเดฟเตฝ เดจเดฟเดจเตเดจเต เดตเต€เดฃเตเดŸเต†เดŸเตเดคเตเดค เดกเดพเดฑเตเดฑเดฏเตเดŸเต† เดชเดฟเดตเดฑเตเดฑเตเด•เตพ เดžเด™เตเด™เตพเด•เตเด•เต เดšเต†เดฏเตเดฏเดฃเดฎเดพเดฏเดฟเดฐเตเดจเตเดจเต.

เดจเดฟเตผเดญเดพเด—เตเดฏเดตเดถเดพเตฝ, เด’เดฐเต เด—เตเดฐเดพเดซเต 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()

Afterword

เด’เดฐเตผเดคเตเดฅเดคเตเดคเดฟเตฝ, เดฎเตเด•เดณเดฟเตฝ เดชเดฑเดžเตเดž เดชเดฐเต€เด•เตเดทเดฃเด‚ เดŠเดทเตเดฎเดณเดตเตเด‚ เดฎเตƒเดฆเตเดตเตเด‚ เดคเดฎเตเดฎเดฟเดฒเตเดณเตเดณ เดคเดพเดฐเดคเดฎเตเดฏเดฎเดพเดฃเต. เดจเดฟเด™เตเด™เตพ เด…เดคเดฟเดจเต†เด•เตเด•เตเดฑเดฟเดšเตเดšเต เดšเดฟเดจเตเดคเดฟเด•เตเด•เตเด•เดฏเดพเดฃเต†เด™เตเด•เดฟเตฝ, เด…เดคเต‡ เดซเดฒเด™เตเด™เตพ เดฒเดญเดฟเด•เตเด•เตเดจเตเดจเดคเดฟเดจเต เด’เดฐเต เด—เตเดฐเดพเดซเต 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()

เด’เดฐเต เดธเต†เด•เตเด•เตปเดกเดฟเตฝ เดคเดพเดดเต†เดฏเตเดณเตเดณ เดชเตเดฐเต‹เดธเดธเตเดธเดฟเด‚เด—เต เดธเดฎเดฏเด‚ เด•เตŠเดฃเตเดŸเต เดŽเดจเดฟเด•เตเด•เต เด‰เตฝเดชเตเดชเดพเดฆเดจเด•เตเดทเดฎเดฎเดพเดฏ เดชเตเดฐเดคเดฟเด•เดฐเดฃเด‚ เดจเต‡เดŸเดพเดจเดพเดฏเดฟเดฒเตเดฒ.

เด•เดฅเดฏเตเดŸเต† เดงเดพเตผเดฎเตเดฎเดฟเด•เดค, เดฎเดจเต‹เดนเดฐเดฎเดพเดฏ เด’เดฐเต เด†เดถเดฏเดตเตเด‚ เดฎเดพเดคเตƒเด•เดพเดชเดฐเดฎเดพเดฏ เดฎเต‹เดกเดฒเดฟเด‚เด—เตเด‚ เด†เดตเดถเตเดฏเดฎเตเดณเตเดณ เดซเดฒเดคเตเดคเดฟเดฒเต‡เด•เตเด•เต เดจเดฏเดฟเด•เตเด•เดฟเดฒเตเดฒ เดŽเดจเตเดจเดคเดพเดฃเต, เด‡เดคเต เด•เตเดฒเดฟเด•เตเด•เตเดนเต—เดธเดฟเดจเตเดฑเต† เด‰เดฆเดพเดนเดฐเดฃเด‚ เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเต เดตเดณเดฐเต† เด‰เดฏเตผเดจเตเดจ เด•เดพเดฐเตเดฏเด•เตเดทเดฎเดคเดฏเต‹เดŸเต† เดชเตเดฐเด•เดŸเดฎเดพเด•เตเด•เตเดจเตเดจเต. เดˆ เดฒเต‡เด–เดจเดคเตเดคเดฟเตฝ เด…เดตเดคเดฐเดฟเดชเตเดชเดฟเดšเตเดšเดฟเดฐเดฟเด•เตเด•เตเดจเตเดจ เด‰เดชเดฏเต‹เด— เด•เต‡เดธเต เด—เตเดฐเดพเดซเต เดกเดฟเดฌเดฟเดŽเด‚เดŽเดธเตเด•เดณเตเดŸเต† เดตเตเดฏเด•เตเดคเดฎเดพเดฏ เดตเดฟเดฐเตเดฆเตเดง เดชเดพเดฑเตเดฑเต‡เดฃเดพเดฃเต, เดŽเดจเตเดจเดฟเดฐเตเดจเตเดจเดพเดฒเตเด‚ เด…เดตเดฏเตเดŸเต† เดฎเดพเดคเตƒเด•เดฏเดฟเตฝ เดฎเต‹เดกเดฒเดฟเด‚เด—เดฟเดจเต เด…เดจเตเดฏเต‹เดœเตเดฏเดฎเดพเดฃเต†เดจเตเดจเต เดคเต‹เดจเตเดจเตเดจเตเดจเต.

เด…เดตเดฒเด‚เดฌเด‚: www.habr.com

เด’เดฐเต เด…เดญเดฟเดชเตเดฐเดพเดฏเด‚ เดšเต‡เตผเด•เตเด•เตเด•