Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RDBの世界をぬりかえていくモデルグラフDB〜truncus graphによるモデルファースト開発〜

RDBの世界をぬりかえていくモデルグラフDB〜truncus graphによるモデルファースト開発〜

ビープラウド社主催の勉強会・BPStudy#205での発表資料となります。概念モデルとDB構造をシームレスに繋ぐ「モデルファースト開発」の説明とそれを実現するモデルグラフDB「truncus graph」の紹介です。以下内容です。

• グラフDBとは何か
• モデルグラフDB truncus graphとは?
• アーキテクチャ
• 事例
• truncus graphによるモデルファースト開発
• ベンチマーク
• GPTsによるモデル自動生成
• TO BE CONT'D …
• コアな話

株式会社Jurabi

September 30, 2024
Tweet

More Decks by 株式会社Jurabi

Other Decks in Programming

Transcript

  1. 会社紹介 3 テクノロジーカンパニー ⚫ 自然言語処理、情報検索、機械学習のエ キスパートチーム ⚫ モデルグラフDB truncus graphを開発

    現実社会を表象するシステム開発をする ⚫ 社会やビジネスをモデル化しそれをシス テムで表象 ⚫ 変化に強いシステム開発 ⚫ 社会のつながり(関係)を表現する 常に最先端技術を追求する ⚫ 科学技術に目を向け、現実社会を紐ほど く チ ンジによる技術 truncus graph 2010 グラフ 構想 初期 2012 2018 中期
  2. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  3. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  4. グラフDBとは何か(1/2) • データ要素をノードとして、その 関連性をエッジとして表現する データベースシステム。 • 関連性の強調: ノード のエッ ジにより、関連性が直接的に表現

    される。 • 柔軟性: 新しいデータや関連性 の追加が容易。 • パフォーマンス: 大量の接続 データを効率的に扱う。 表形式 グラフ
  5. グラフDBとは何か(1/2) • 一般的なプラットフォーム • Neo4j • ArrangoDB • Amazon Neptune

    • etc • 従来の用途 • ソーシャルネットワーキング、レコメンドシステム、不正 知、ネット ワーク管 、MDM
  6. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  7. モデルグラフDB truncus graph とは ? • スキーマをサポートしたグラフDB • モデルを書くだけでOK ⇒

    ER図不要! • モデルとストアが直結、自然かつ効率的につながる ⇒ ORM/OGMなどは不要、InProcess • エンティティ の関連はすべてインデックス付けされている
  8. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  9. 例) truncus graphで作ったECアプリの構 Usecase層(Application層) Domain層 例) truncus graphで作ったECアプリの構 Domain Model

    Domain Service Usecacse(更新系) Usecase Model Usecacse(読込系) イヤードアーキテクチ
  10. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  11. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  12. truncus graphによるモデルファースト開発 お題: 簡易的なショッピングサイトを作 • モデル定義 • RDB • truncus

    graph • サービス実装 • RDB • truncus graph 顧客、注文、注文明細、商品 ある顧客の買った商品の一覧を取得するサービス
  13. 概念モデル⇔テーブル定義のギ ップ • 概念モデルがそのままER図になるわけではない • 階層構造をもったオブジェクトの表現 • 値オブジェクトへの一対多の対応 • 多対多の関連の場合、中

    テーブルが必要 • O/Rマッパーでギ ップを埋められるか? • O/Rマッパーを用いたモデル定義をする事も多い • 概念モデルをある程度そのまま反映可能な事もある
  14. O/Rマッパー(JPA)を使ったモデル定義例 @Entity @Table(name = “orders”) public class Order { @Id

    private Long id; @Embedded private Address shippingAdress;//配送先住所 @OneToMany(mappedBy = "orders") private List<OrderDetail> orderDetails; @ManyToOne private Customer customer; } @Entity public class Customer { @Id private Long id; private String name; @Embedded private Address address; // 現住所 @OneToMany @JoinColumn(mappedBy = "customer") private List<Order> orders; } 住所はモデル通りに表現 注文明細はリスト として表現
  15. truncus graph でのモデル定義 // 注文 public interface Order extends Entity

    { Relation<Customer> customer(); Attribute<Address> shippingAddress(); Sequence<Attribute<OrderDetail>> orderDetails(); } // 顧客 public interface Customer extends Entity { Attribute<String> name(); Attribute<Address> address(); } ① ② ③ ④ ⑤ 概念モデルをそのままの形で実装できる(ER図不要!) ① ② ③ ④ ⑤
  16. truncus graphによるモデルファースト開発 お題: 簡易的なショッピングサイトを作 • モデル定義 • RDB • truncus

    graph • サービス実装 • RDB • truncus graph ある顧客の買った商品の一覧を取得するサービス
  17. N+1問題:注文×注文明細分のSQLが発行される // 顧客の注文(orders)を取得 List<Order> orders = orderRepository.findByCustomerID(customerId); // 注文(orders)の数分、クエリ発行 return

    orders.stream() .flatMap(order -> order.getOrderDetails().stream()) .map(od -> { // 注文明細(OrderDetails)の数分、クエリ発行 Product product = productRepository.findById( od.getProduct().getProductID()); return new PurchasedProductResponse(...); }).collect(Collectors.toList()); ある顧客が購入した商品と数量の一覧 直観的だが発行されるクエリの回数 を制御できない ループによる単純な実装例:
  18. N+1問題:JOINのネストでN+1問題を回避 @Query("SELECT new ec.app.api.PurchasedProductResponse( od.product.productId, od.quantity, od.purchasePrice, p.productName) " +

    "FROM OrderDetail od " + "JOIN od.orders o " + "JOIN Product p ON od.product.productId = p.productId " + "WHERE o.customer.customerId = :customerId") List<PurchasedProductResponse> findPurchasedProductsByCustomerId( @Param("customerId") String customerId); • JOINを用いているのでインデックス次第 で速くなる • SQLライクではあるがJPQLの知識が必要 • SQLも書けるが抽象化は破れる ある顧客が購入した商品と数量の一覧 JPQLでメソッドを定義する例:
  19. truncus graphによるモデルファースト開発 お題: 簡易的なショッピングサイトを作 • モデル定義 • RDB • truncus

    graph • サービス実装 • RDB • truncus graph ある顧客の買った商品の一覧を取得するサービス
  20. truncus graphでのサービス実装 var customer = repository.get(customerId, Customer.class); var orders =

    customer.getReverseRelation(Order.class, "customer"); orders.forEach((id, rel) -> { var order = rel.target(); order.orderDetail().forEach(attr -> { var orderDetail = attr.value(); var product = orderDetail.product().target(); ... }); }); ①IDをキーにして顧客を取得 ① ある顧客が購入した商品と数量の一覧
  21. truncus graphでのサービス実装 var customer = repository.get(customerId, Customer.class); var orders =

    customer.getReverseRelation(Order.class, "customer"); orders.forEach((id, rel) -> { var order = rel.target(); order.orderDetail().forEach(attr -> { var orderDetail = attr.value(); var product = orderDetail.product().target(); ... }); }); 逆 関 連 ②注文→顧客の逆向きの関連を たどって注文を取得 ② ある顧客が購入した商品と数量の一覧
  22. truncus graphでのサービス実装 var customer = repository.get(customerId, Customer.class); var orders =

    customer.getReverseRelation(Order.class, "customer"); orders.forEach((id, rel) -> { var order = rel.target(); order.orderDetail().forEach(attr -> { var orderDetail = attr.value(); var product = orderDetail.product().target(); ... }); }); ③注文に紐づく注文明細を取得する ③ ある顧客が購入した商品と数量の一覧
  23. truncus graphでのサービス実装 var customer = repository.get(customerId, Customer.class); var orders =

    customer.getReverseRelation(Order.class, "customer"); orders.forEach((id, rel) -> { var order = rel.target(); order.orderDetail().forEach(attr -> { var orderDetail = attr.value(); var product = orderDetail.product().target(); ... }); }); ④注文明細→商品の関連をたどって 商品を取得する ④ ある顧客が購入した商品と数量の一覧
  24. truncus graphでのサービス実装 var customer = repository.get(customerId, Customer.class); var orders =

    customer.getReverseRelation(Order.class, "customer"); orders.forEach((id, rel) -> { var order = rel.target(); order.orderDetail().forEach(attr -> { var orderDetail = attr.value(); var product = orderDetail.product().target(); ... }); }); グラフデータベースなので、関連を"簡単に効率的に"取得できる! (JPAだと効率的にするための工夫が必要になる) クエリ不要! ある顧客が購入した商品と数量の一覧
  25. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  26. ベンチマーク 100万 10万 1億 2億 truncus graph RDB 5回の平均 12.02秒

    → 2.36秒 47.6秒 → 0.74秒 チューニング後 チューニング ・truncus graph: キャッシュサイズ変更 ・RDB: index作成、クエリ最適化、パラメータ変更 1. 顧客の注文した商品の一覧を取得する (100顧客 )
  27. ベンチマーク 100万 10万 1億 2億 truncus graph RDB 1回目 10.9秒

    2.4秒 2〜5回目平均 0.21秒 0.33秒 5回の平均 2.36秒 0.74秒 チューニング後 チューニング ・truncus graph: キャッシュサイズ変更 ・RDB: index作成、クエリ最適化、パラメータ変更 1. 顧客の注文した商品の一覧を取得する (100顧客 )
  28. ベンチマーク 2. Wikidataの関連をたどって 「鳥山明」→「夏目漱石」の最短経路を探す WITH RECURSIVE edge_path AS ( SELECT

    edge_id, src_id, tgt_id FROM wikidata WHERE src_id = '鳥山明のID' UNION ALL SELECT w.edge_id, w.src_id, w.tgt_id FROM wikidata w INNER JOIN edge_path ep ON ep.tgt_id = w.src_id ) SELECT edge_id FROM edge_path WHERE tgt_id = '夏目漱石のID'; RDBでのクエリ(1):”WITH RECURSIVE”で再起的に探
  29. ベンチマーク 2. Wikidataの関連をたどって 「鳥山明」→「夏目漱石」の最短経路を探す @Query(value = "SELECT * FROM wikidata

    w WHERE w.src_id IN (:srcIds)" , nativeQuery = true) List<Wikidata> findChainBySrcIds(@Param("srcIds") List<String> srcIds); RDBでのクエリ(2):ホップごとにクエリを発行
  30. ベンチマーク 2. Wikipediaのリンクをたどって 「鳥山明」→「夏目漱石」の最短経路を探す truncus graph RDB 平均 57.96秒 156.9秒

    結果 [鳥山明] → [パラダイス文書] → [パンドラ文書] → [ペドロ・パブロ・クチンスキー] → [ジャン=リュック・ゴダール] → [金獅子賞] → [黒澤明] → [羅生門] → [芥川龍之介] → [夏目漱石]
  31. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  32. TO BE CONT'D... • AIとの協調 • モデル・スキーマ・クエリ生 • モデルマーケットプ イス構想

    • NewSQL的な並列書き込みクラスターの実装 • truncus graph as a Service • パフォーマンスの強化
  33. GPTsによるモデルの生 生 されたモデル(抜粋) 生 されたクエリ static Stream<Order> findByCustomerName(GraphQueryExecutor queryExecutor, String

    customerName) { var result = queryExecutor.execute( "MATCH (c:`test:Customer`{name:'" + customerName + "'})- [:customer]->(o:`test:Order`) RETURN o"); return result.map(record -> { var de = (DomainEntity) record.get("o"); var entity = de.narrow(Order.class); return entity; }); }
  34. 発表内容 • グラフDBとは何か • モデルグラフDB truncus graphとは? • アーキテクチ •

    事例 • truncus graphによるモデルファースト開発 • ベンチマーク • TO BE CONT’D … • コアな話
  35. truncus graphに至る背景(2) • 開発においてモデリングを重視する方向性になっていた • 何故グラフDBとモデリングが結びつけられたか? • オブジェクトのフィールド=プロパティグラフのノードにおけるプロパティ ではないのか? •

    Neo4Jなどはプロパティに制限があるが、理屈の上では無制限で良いはず • 型付けができた方が整合性の観点で好ましい • エンティティからエンティティの参照はグラフのエッジでしかない
  36. イフィケーションのイメージ(1) // 型の世界 type X { a: string; b: integer;

    c: boolean; y: Y; } type Y { p: string; q: integer; } type Z extends Y { r: boolean; } // データの世界 x = { : ”aaa” b: 0; c: true; y: y; } y: Y = { : ” 1”; q: 1; } z: Z = { : ” 2”; q: 2; r: true; }
  37. イフィケーションのイメージ(2) // 型の世界 // あるいはソースの世界 type X { a: string;

    b: integer; c: boolean; y: Y; } type Y { p: string; q: integer; } type Z extends Y { r: boolean; } // データの世界(インスタンス) // あるいはランタイムの世界 x = { : ”aaa” b: 0; c: true; y: y; } y: Y = { : ” 1”; q: 1; } z: Z = { : ” 2”; q: 2; r: true; } // データの世界(型オブジェクト) // あるいはランタイムの世界 Type<X> = { a: Type<string> b: Type<integer>; c: Type<boolean>; y: Type<Y>; } Type<Y> = { p: Type<string>; q: Type<integer>; } Type<Z> = Type<Y> + { r: Type<boolean> }
  38. イフィケーションのイメージ(3) Type<X> = { a: Type<string> b: Type<integer>; c: Type<boolean>;

    y: Type<Y>; } Type<Y> = { p: Type<string>; q: Type<string>; } Type<Z> = Type<Y> + { r: Type<boolean> } type X a: string; b: integer; c: boolean; type Y p: string; q: integer; type Z r: boolean; relation y extends
  39. イフィケーションのイメージ(4) type X a: string; b: integer; c: boolean; type

    Y p: string; q: integer; relation y x0 : “aaa” b: 0 c: true y0 : “ 1” q: 1
  40. イフィケーションのイメージ(5) 実装言語 truncus graph 一般的なグラフDB RDB 型=集合 型=集合 型なし、ノードはラ ベルやプロパティで

    頑張って識別 テーブル=関係の 集合 プロパティの型は 由 プロパティの型は 由 プロパティの型に制 限あり 属性の型に制限 あり エンティティ=ノード エンティティ=ノード エンティティ=ノード エンティティ=述 値オブジェクト=プロパ ティ 値オブジェクト=プロパ ティ 値オブジェクト=プロ パティ、あるいは独 立したノード 値オブジェクト= 関係あるいは述 関連=写像(メソッド) 関連=型付けされたエッジ 関連=エッジ、ただし 厳密な型付けはない 関連=関係比較演 算子
  41. イフィケーションとProxyによるデータ操作(2) モデルの世界 GraphDBの世界 ランタイムの世界 interface Entity1 Entity2 Entity3 Node1 Node1

    Node3 Proxy Proxy Proxy Proxy Proxy Proxy 3つの世界を繋ぐのが イフィケーションのアイディア RTTI