【redmine.tokyo第25回勉強会発表資料】

Redmineデータのグラフデータ化によりシステム監視・運用業務を効率化～ 関連チケットの可視化、類似チケットのレコメンド ～2023年11月4日
NTTコムウェア株式会社
ネットワーククラウド事業本部NWソリューション部TNX-BU
Copyright © NTT COMWARE CORPORATION 2023

1

会社・組織紹介

NWクラウド事業本部
NWソリューション部

 NWを知り尽くし、ミッションクリティカルなシステムを開発・運用できるシステムインテグレーター
 Redmineは、組織としてもプロジェクト管理等で広く利用されている
Copyright © NTT COMWARE CORPORATION 2023

2

本日紹介したいこと【その1】
グラフデータベースとはグラフデータベース(グラフDB)の概要、リレーショナルデータベース(RDB)とグラフDBの性能検証結果の紹介【その2】
RDBとグラフDBの連携ソリューション紹介
RDBから任意のデータをグラフ形式に変換しリアルタイムでグラフDBに反映するソリューション”Graphyde”を少しだけ紹介【その3】
Redmineデータのグラフデータ化とその活用
Redmineで管理しているシステム監視・運用業務のチケットデータをグラフデータ化し、そのデータを活用して業務を効率化す
る方法をデモも交えて紹介
Copyright © NTT COMWARE CORPORATION 2023

3

【その1】
グラフデータベースとはグラフデータベース(グラフDB)の概要、リレーショナルデータベース(RDB)とグラフDBの性能検証結果の紹介

Copyright © NTT COMWARE CORPORATION 2023

4

１．グラフデータベースとは
NoSQLに分類
グラフ理論に基づく、グラフ構造に最適化
点(ノード)と線(リレーション、エッジともいう)で構成
ネットワーク状になっているデータの管理に有効
Neo4jが圧倒的シェア
ソーシャルネットワーク、経路検索、NWやICTリソースの管理、不正検知等で使われている※但し、現在、日本国内ではあまり使われていない!
2018年私たちが国内で初めてNeo4jを利用したシステムをリリース
表とグラフどちらが直感的?
日本でもそろそろブーム到来?

 2021年3月のガートナーレポートでは、データ解析分野の約10％でグラフ技術が利用されているが2025年には80％まで利用率が上がると予想されている Oracle最新バージョン(23c)にGraph機能が実装された
Copyright © NTT COMWARE CORPORATION 2023

5

【参考】グラフDBの構成要素
ラベル名
駅
東京
住所:丸の内ノード
山手線
距離:1815m

プロパティ

駅
神田
住所:鍛冶町山手線
距離:1725m

駅
秋葉原
住所:外神田

タイプ名
京浜東北線

リレーション(エッジ)

距離:3535m

プロパティ
Copyright © NTT COMWARE CORPORATION 2023

6

２．RDBとグラフDBの検索処理
RDBの検索処理
 表を順次検索、それをSQLで結合して結果を出力
 よって、検索対象の表が多く、結合条件が複雑になればなるほど、パフォーマンスが劣化
グラフDBの検索処理 ノードとノードの関係を表すリレーション情報をあらかじめ実態として保持 そのため、ノードからノード、更にその先にひもづくノードの情報を即座に抽出することが可能
グラフデータのイメージ

ノード

Copyright © NTT COMWARE CORPORATION 2023

リレーション7

３．RDBとグラフDBの性能検証
３-１．今回ターゲットにした複雑度
以下はNeo4j社の検証結果（RDB）（グラフDB）

私たちが扱う通信ネットワークの構成情報を取得するには、これくらいのテーブル数を結合する必要あり「https://neo4j.com/blog/oracle-rdbms-neo4j-fully-sync-data/」より抜粋

Copyright © NTT COMWARE CORPORATION 2023

8

３．RDBとグラフDBの性能検証
３-２．検証で利用したデータモデル
 検証に使用したNW構成を表すデータモデル
起点ビル
Building

終点ビル
Building

Element

Element
Rack

Rack
Unit

Unit

Card

Card

SubCard
Termination
Termination
Point
Termination
Point
Point

Copyright © NTT COMWARE CORPORATION 2023

SubCard
Trail
Trail

Termination
Termination
Point
Point

Trail

Termination
Point

9

３．RDBとグラフDBの性能検証
３-３．複数データの比較結果
複雑な複数データの検索（検証合計データ:12,500,000件）
ビルを跨るネットワークと、そのネットワークを収容するビル内の設備情報を検索 2パターンでNW構成を検索(a)起点ビルと終点ビルを指定:NW数2,000件抽出(b)起点ビルのみ指定:NW数20,000件抽出

(a)
(b)

パターン

(a)

44.287秒

2.512秒(b)4,851,142秒（約80分51秒）

平均20.626秒

Copyright © NTT COMWARE CORPORATION 2023

10

【参考】性能検証で使用したSQL
性能検証(a)および(b)のSQL
SELECT DISTINCT
a_side.building_code AS a_building_code, a_side.building_name AS a_building_name, a_side.physical_device_id AS a_physical_device_id, z_side.building_code AS z_building_code, z_side.building_name AS z_building_name, z_side.physical_device_id AS z_physical_device_id, a_trail.trail_id AS trail_id
FROM (
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv
JOIN equipment_holder_cm AS eh_rack ON pd.physical_device_id = eh_rack.physical_device_id
JOIN equipment_holder_rack_nv AS rack_nv ON eh_rack.equipment_holder_id = rack_nv.equipment_holder_id-- shelf
JOIN equipment_holder_cm AS eh_shelf ON eh_rack.equipment_holder_id = eh_shelf.parent_equipment_holder_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard
JOIN equipment_holder_cm AS eh_subslot ON eh_slot.equipment_holder_id = eh_subslot.parent_equipment_holder_id
JOIN equipment_cm AS eq_subcard ON eh_subslot.equipment_holder_id = eq_subcard.equipment_holder_id
JOIN equipment_subcard_nv AS subcard_nv ON eq_subcard.equipment_id = subcard_nv.equipment_id-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON eq_subcard.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv：なし-- shelf
JOIN equipment_holder_cm AS eh_shelf ON pd_nv.physical_device_id = eh_shelf.physical_device_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard
JOIN equipment_holder_cm AS eh_subslot ON eh_slot.equipment_holder_id = eh_subslot.parent_equipment_holder_id
JOIN equipment_cm AS eq_subcard ON eh_subslot.equipment_holder_id = eq_subcard.equipment_holder_id
JOIN equipment_subcard_nv AS subcard_nv ON eq_subcard.equipment_id = subcard_nv.equipment_id-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON eq_subcard.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv
JOIN equipment_holder_cm AS eh_rack ON pd.physical_device_id = eh_rack.physical_device_id
JOIN equipment_holder_rack_nv AS rack_nv ON eh_rack.equipment_holder_id = rack_nv.equipment_holder_id-- shelf
JOIN equipment_holder_cm AS eh_shelf ON eh_rack.equipment_holder_id = eh_shelf.parent_equipment_holder_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON card_nv.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOINCOMWARE
physical_device_trans_nv
AS pd_nv ON pd.physical_device_id= pd_nv.physical_device_id
Copyright © NTT
CORPORATION
2023-- rack_nv：なし-- shelf
JOIN equipment_holder_cm AS eh_shelf ON pd_nv.physical_device_id = eh_shelf.physical_device_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON card_nv.equipment_id = ttp.equipment_id-- trail_cm
JOIN trail_cm AS trail ON (ttp.trail_termination_point_id = trail.a_trail_termination_point_id
OR ttp.trail_termination_point_id = trail.z_trail_termination_point_id)
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv：なし-- shelf：なし-- card：なし-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON pd.physical_device_id = ttp.physical_device_id) AS a_side
JOIN trail_cm AS a_trail ON (a_side.ttp_id = a_trail.a_trail_termination_point_id
OR a_side.ttp_id = a_trail.z_trail_termination_point_id),(
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv
JOIN equipment_holder_cm AS eh_rack ON pd.physical_device_id = eh_rack.physical_device_id
JOIN equipment_holder_rack_nv AS rack_nv ON eh_rack.equipment_holder_id = rack_nv.equipment_holder_id-- shelf
JOIN equipment_holder_cm AS eh_shelf ON eh_rack.equipment_holder_id = eh_shelf.parent_equipment_holder_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard
JOIN equipment_holder_cm AS eh_subslot ON eh_slot.equipment_holder_id = eh_subslot.parent_equipment_holder_id
JOIN equipment_cm AS eq_subcard ON eh_subslot.equipment_holder_id = eq_subcard.equipment_holder_id
JOIN equipment_subcard_nv AS subcard_nv ON eq_subcard.equipment_id = subcard_nv.equipment_id-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON eq_subcard.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv：なし-- shelf
JOIN equipment_holder_cm AS eh_shelf ON pd_nv.physical_device_id = eh_shelf.physical_device_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard
JOIN equipment_holder_cm AS eh_subslot ON eh_slot.equipment_holder_id = eh_subslot.parent_equipment_holder_id
JOIN equipment_cm AS eq_subcard ON eh_subslot.equipment_holder_id = eq_subcard.equipment_holder_id
JOIN equipment_subcard_nv AS subcard_nv ON eq_subcard.equipment_id = subcard_nv.equipment_id-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON eq_subcard.equipment_id = ttp.equipment_id

UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv
JOIN equipment_holder_cm AS eh_rack ON pd.physical_device_id = eh_rack.physical_device_id
JOIN equipment_holder_rack_nv AS rack_nv ON eh_rack.equipment_holder_id = rack_nv.equipment_holder_id-- shelf
JOIN equipment_holder_cm AS eh_shelf ON eh_rack.equipment_holder_id = eh_shelf.parent_equipment_holder_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON card_nv.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv：なし-- shelf
JOIN equipment_holder_cm AS eh_shelf ON pd_nv.physical_device_id = eh_shelf.physical_device_id
JOIN equipment_holder_shelf_nv AS shelf_nv ON eh_shelf.equipment_holder_id = shelf_nv.equipment_holder_id-- cardJOIN equipment_holder_cm AS eh_slot ON eh_shelf.equipment_holder_id = eh_slot.parent_equipment_holder_id
JOIN equipment_cm AS eq_card ON eh_slot.equipment_holder_id = eq_card.equipment_holder_id
JOIN equipment_card_nv AS card_nv ON eq_card.equipment_id = card_nv.equipment_id-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON card_nv.equipment_id = ttp.equipment_id
UNION
SELECTbuil.building_code AS building_code, buil.name AS building_name, pd.physical_device_id AS physical_device_id, ttp.trail_termination_point_id AS ttp_id
FROM
building_ci AS buil-- physical_device
JOIN physical_device_cm AS pd ON buil.building_code = pd.building_code
JOIN physical_device_trans_nv AS pd_nv ON pd.physical_device_id = pd_nv.physical_device_id-- rack_nv：なし-- shelf：なし-- card：なし-- subcard：なし-- trail_termination_point
JOIN trail_termination_point_cm AS ttp ON pd.physical_device_id = ttp.physical_device_id) AS z_side
JOIN trail_cm AS z_trail ON (z_side.ttp_id = z_trail.a_trail_termination_point_id
OR z_side.ttp_id = z_trail.z_trail_termination_point_id)
WHERE
a_side.building_code = '1310400101' -- Aビル-- AND z_side.building_code = ‘1310611001’ -- Bビル ★対地ビルにBビルを指定する場合は本行のコメントを外す
AND a_trail.trail_id = z_trail.trail_id;11【参考】性能検証で使用したCypher Query
性能検証(a)のCypher Query
MATCH(b1:Build)<-[]-(pd1:PhysicalDevice)<-[]-(trail:Trail)-[]->(pd2:PhysicalDevice)-[]->(b2:Build)
WHERE
b1.building_id = ‘13104 ‘ // 起点ビル
ANDb2.building_id = ‘13106 ‘ // 終点ビル
RETURNb1.building_id, b1.name, trail.trail_id, b2.building_id, b2.name;

性能検証(b)のCypher Query
MATCH(b1:Build)<-[]-(pd1:PhysicalDevice)<-[]-(trail:Trail)-[]->(pd2:PhysicalDevice)-[]->(b2:Build)
WHERE
b1.building_id = ‘13104 ‘ // 起点ビル
RETURNb1.building_id, b1.name, trail.trail_id, b2.building_id, b2.name;
Copyright © NTT COMWARE CORPORATION 2023

12

３．RDBとグラフDBの性能検証
３-４．単一データの比較結果
単一データの検索（検証合計データ:21,000,000件）
 2つの項目のAND条件に合致する60件のデータを抽出

0.000948秒（0.948ミリ秒）
ID
管理対象・・ ・・・
3 Server4 VirtualMachine
5 OS・・ ・・・
12 Server
・・ ・・・
21 VirtualMachine

名称
・・・
HW1
VM1
OS1
・・・
HW2
・・・
VM2

RDBは単純な表走査なので高速
Copyright © NTT COMWARE CORPORATION 2023

13.362秒（13,362ミリ秒）

グラフDBは全体から特定のノードを見つけるのが苦手
13

４．RDBとグラフDBの使い分け
RDBを利用 単一データなど比較的シンプルな検索 曖昧検索グラフDBを利用
 結合データ数が多い等の複雑な検索

RDBとグラフDBのいいとこ取り!

Copyright © NTT COMWARE CORPORATION 2023

ハイブリッド利用を推奨!

14

【その2】RDBとグラフDBの連携ソリューション紹介
RDBから任意のデータをグラフ形式に変換しリアルタイムでグラフDBに反映するソリューション”Graphyde”を少しだけ紹介

Copyright © NTT COMWARE CORPORATION 2023

15

１．実案件から提唱するハイブリッドDBシステム
 Graphydeは実案件で組み立ててきたノウハウをもとに作成した「簡単・迅速!すぐできるグラフデータ!」がコンセプトのRDBとグラフDBのリアルタイムなデータ連携を可能とするソリューション RDBとグラフDBのいいとこ取りをしたハイブリッドDBシステムを簡単・迅速に構築可能
災害時に影響を受けるNWの範囲を把握するシステム

ここの仕組みをソリューション化

 整合性の担保、単一データ検索に優れたRDB
 つながり情報の分析、高速抽出に優れたグラフDB
 いいとこ取りのハイブリッドDBシステム構築、提唱

グラフDBを簡単に利用できるようにしたい!
Graphyde Sync※「Graphyde」は私たちが命名したNTTコムウェア株式会社の登録商標です
Copyright © NTT COMWARE CORPORATION 2023

16

２．Graphyde Syncとはお客様の課題・要求••••

RDBのデータ構造が複雑化し、データ抽出に時間が掛かる
データ分析のためにグラフDBを利用したいが、グラフデータ構築のノウハウがない
既にあるデータをグラフ化して、データの関係性を可視化、分析したい
RDBとグラフDBのいいとこ取りをしたハイブリッドDBシステムを構築したい

Graphyde Sync

 新規システムだけでなく、既存のシステムにも簡単にグラフDB(Neo4j)を組み込むことが可能
 RDBを操作(登録、更新、削除)するだけで、自動的にリアルタイムでデータがグラフDBに流通

3つの画面機能とリアルタイム同期機能をパッケージング
データ同期までの3つのステップを実現するWeb画面
DB接続情報設定

マッピング設定

RDB

簡単にグラフデータを作成できる!

グラフDB
リアルタイム同期

Copyright © NTT COMWARE CORPORATION 2023

リアルタイム同期
起動/停止

RDBを使いながらグラフDBも使える!

つながり情報の可視化
データの高速検索
データ活用、分析
17

【参考】データ同期までの3つのステップ① RDBとグラフDBの接続情報を設定② RDBからグラフDBへ展開したいテーブルやカラム、テーブル間の関係を指定することで、RDBとグラフDBのマッピングを設定③ RDBのデータを即座にグラフDBに反映するリアルタイム同期機能の起動と停止
マッピング一覧（トップページ）①①接続するDBの情報設定①DB情報設定画面

Copyright © NTT COMWARE CORPORATION 2023②③

②RDBとグラフDBのマッピング設定②マッピング設定画面③リアルタイム同期機能の起動③リアルタイム同期起動／停止画面

18

【参考】Graphyde Syncの動作環境
動作環境
Graphyde Syncは以下の環境で動作することを確認しています。
 Graphyde SyncはLinux(※1)にインストール
 Java(※2)のインストールが必要 ブラウザは”Chrome”と”FireFox”で動作することを確認※1:CentOS7、Ubuntu20で動作することを確認しています※2:Javaのバージョンは8.0以降で動作することを確認しています

対象データベース
Graphyde Syncが対応するデータベースを以下に示します。
グラフDB

対象のバージョン

Neo4j

4.0以降

RDB ※3

対象のバージョン

PostgreSQL

10以降

MySQL

5.6以降

※3:現在、 Oracle、SQL Serverについても動作確認中です
Copyright © NTT COMWARE CORPORATION 2023

19

【参考】世界のデータベーストレンドと私たちの歩み
グラフDBは世界で最も注目を集めている
2023年3月
マッピング設定にもとづいてグラフDBを復旧する”Graphyde Recover”試作品作成
2022年1月
RDBとグラフDBのリアルタイム連携ソリューション
”Graphyde Sync”β版作成
2020年12月
RDBとグラフDBのリアルタイム連携する
仕組みの試作品作成
2019年8月
某Smart City案件のシステムリリース
RDBとグラフDBのリアルタイム同期＋時系列管理を実現
2018年3月
グラフDBを使ったNW管理システムリリース
つながり情報高速抽出を実現
2017年6月
グラフDB本格検討開始

Copyright © NTT COMWARE CORPORATION 2023
https://db-engines.com/en/ranking_categories

20

【その3】
Redmineデータのグラフデータ化とその活用
Redmineで管理しているシステム監視・運用業務のチケットデータをグラフデータ化し、そのデータを活用して業務を効率化する方法をデモも交えて紹介

Copyright © NTT COMWARE CORPORATION 2023

21

１．システム運用業務のRedmineプロジェクト
 以下は、あるシステムの運用業務で利用しているプロジェクトで、各チケットは相互に深く関連障害

01
インシデントチケット(アラートチケット)

50
問い合わせ・依頼
チケット

ホストチケット

02
問題チケット(サーバ・NW機器等の情報)

ナレッジチケット03
変更チケット60
サービスオーダー
チケット

10
運用保守チケット04
商用作業チケット:自動起票
Copyright © NTT COMWARE CORPORATION 2023

:手動起票

22

２．Redmineデータのグラフデータ化とその活用
 Zabbixで検知したアラートをインシデントチケットとして、ホストチケットとともに自動起票 Graphyde SyncによりRedmineのRDBデータをグラフデータ化し、システム運用業務に活用
システム監視インシデントチケット/
ホストチケットを
インシデント管理・システム運用管理
自動起票

グラフDB ※3

グラフDB

RDB

Graphyde Syncを使ってRDBのデータをグラフデータ化
Copyright © NTT COMWARE CORPORATION 2023

システム運用業務にグラフデータを活用

システム監視データ

チケット管理データ

23

３．具体的なアーキテクチャ
システム運用・保守
チケット画面のERBファイル“show.html.erb”に以下を追加(/app/views/issues/show.html.erb)

インシデント#1038<hr /><b>グラフデータ活用:</b><%= link_to “【関連チケット表示】", "http://xxx.xxx.xx.xx/redmine/issues/#{h @issue.id}", target:"_blank".html_safe %>【類似チケット表示】<%= link_to "類似度順10件", "http://xxx.xxx.xx.xx:5000/similar_issues/#{h @issue.id}", target:"_blank".html_safe %>／<%= link_to "類似度50％以上", "http://xxx.xxx.xx.xx:5050/similar_issues_50/#{h @issue.id}", target:"_blank".html_safe %>関連チケット表示
類似チケット表示

関連チケット表示
Vue.jsCytoscape.js
Node.js

類似チケット表示

Python
Flask

システムA

システムB

アラート

アラート

ZABBIX

RedmineNeo4j・システム監視・アラート一覧表示
・監視対象機器の状態確認
・監視設定 等・インシデント管理
・問題管理/変更管理・ナレッジ管理 等

・チケット間の関連付け
・ホスト/アラートの関連付け
・グラフデータサイエンス 等

・
・
・
システムZ

インシデント/ホスト
チケット自動起票

Graphyde Sync
RDB

(RDBのグラフデータ化)

グラフDB

Redmine API
アラート

PythonJava※同一アラートは集約

RedmineのAPIを使って以下を実施
・インシデントチケットの自動起票・ホストチケットの検索、存在しなければ自動起票
・インシデントチケットとホストチケットを自動で関連付け

Copyright © NTT COMWARE CORPORATION 2023

RDBとグラフDBのハイブリッドDBシステム:私たちが独自に開発した部分

24

４．関連チケットの可視化（つながり情報可視化） アラートにより起票されたインシデントチケットとホストチケット、関連チケットをグラフDBで紐づけ
 それにより障害が発生時、どこのホストで発生したアラートか、アラートが集中している個所はど
こか、視覚的かつ即座に判別が可能
関連チケット表示

ホストチケット(サーバ・NW機器)
このサーバにアラートが集中していることがわかる

インシデントチケット(発生アラート)

Copyright © NTT COMWARE CORPORATION 2023

25

５．類似チケットのレコメンド
 インシデントの対応時、グラフデータサイエンスの活用により過去の類似インシデントのチケットおよび関連チケットを抽出することで、迅速な原因解析、適切な対処・対応が可能
類似チケット表示

Copyright © NTT COMWARE CORPORATION 2023

26