Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

3000社の業務データ絞り込みを支える技術

4,003 views

Published on

Developers Summit 2017 KANSAI の発表資料です。

3000社の業務データ絞り込みを支える技術
kintoneのアーキテクチャと高速化

Published in: Technology
  • Be the first to comment

3000社の業務データ絞り込みを支える技術

  1. 1. 3000社の業務データ 絞り込みを支える技術 kintoneの アーキテクチャと高速化 サイボウズ大阪開発部 三苫 亮 2017/09/08 Developers Summit 2017 KANSAI
  2. 2. 自己紹介 三苫 亮(みとま りょう) • @mitomasan • サーバーサイドエンジニア • Java, DB周りが好き • サイボウズ大阪開発部で kintone という製品の開発をしています。
  3. 3. 今日のお話 スキーマ不定な業務データを扱うための kintone の現行アーキテクチャの解説と Elasticsearch をもちいて 絞り込みを高速化するお話(WIP)
  4. 4. お話のながれ • スキーマ不定データの格納・絞り込み • kintone の絞り込み • パフォーマンスの問題 • Elasticsearch の概要 • 対策の概要と結果・トレードオフ • まとめ
  5. 5. スキーマ不定データの 格納・絞り込み
  6. 6. データをデータベースに格納する
  7. 7. どんなデータを?
  8. 8. 同級生の名簿? 名前 性別 学年 つながり 共通の趣味
  9. 9. ラーメン屋のリスト? 店名 住所 ジャンル 評価
  10. 10. 売上伝票? 伝票番号 売上額 品名 単価 品名 単価 品名 単価 …
  11. 11. データの形はさまざま
  12. 12. スキーマという スキーマ=構造 データはそれぞれ構造を持っている
  13. 13. 構造が事前にわかっているとシステムは処理しやすい スキーマを定義して固定する 店名が天一で評価の高い ラーメン屋が知りたいな 店名 住所 評価 … 天一 S
  14. 14. RDBMSの基本はスキーマ固定 友達テーブル 名前 連絡先 地元 構造を先に決めちゃう (=テーブルを定義する) バイト先 エピソードテーブル 友達名 日時 エピソード
  15. 15. スキーマレスって知ってる? • スキーマレスDBという言葉をよく聞くね • つまり構造が無い • ベースラインとする構造は あるだろうけれど それを逸脱するデータも許容する🙆
  16. 16. スキーマ不定なデータというのもある • 構造が一定のままではないデータ • 構造はあるけど、変わる • その時点の構造に合わないデータは許容しない🙅 • スキーマレスとは似て非なる言葉 名前 性別 名前 性別 学年 名前 性別 職業 収入
  17. 17. イメージとしては… あくまでイメージね • スキーマレス • ぜ~んぶ連想配列/Map/Hashでやっちゃうよ~☺ • カウボーイっぽい世界観 • スキーマ不定 • 型定義はするんだけど、実行時に途中で型変えちゃうよ • Rubyっぽい世界観 • スキーマ固定 • 実装時に型定義して、実行時に変更は許さないよ • Javaっぽい世界観
  18. 18. スキーマ不定 どんな時に使われる? • 構造をあらかじめ決められないとき • 答えが決まっていなくてもとにかく始めたい • 決定している項目は系統立てて格納・絞り込み・集計したい • その時の必要に合わせて構造を変更したい ビジネスの現場でありがちな要求 また話が 変わったようだな
  19. 19. 話は変わってkintone • スキーマを自由に設計できるWebデータベース (=システムの稼働中にテーブルにあたるものを定義する) • スキーマ不定データが扱える ドラッグ&ドロップで データベースの項目を 設計・変更できる
  20. 20. でもkintoneのバックエンドはRDBMS えっ!? スキーマ不定のシステムなのに、 バックエンドはスキーマ固定の RDBMSなんですか??? RDBMS
  21. 21. RDBMSでスキーマ不定データを扱う RDBMSでスキーマ不定データを扱うアプローチは大きく4つ • 構造写像アプローチ • モデル写像アプローチ • friendfeedアプローチ • salesforceアプローチ 参考:http://dev.ariel-networks.com/Members/inoue/schemaless/
  22. 22. 構造写像アプローチ • データの構造を、RDBMS上に構築する • つまり普通のデータベースと同じ • メリット • RDBMSの機能がそのまま使える • パフォーマンス • デメリット • 構造を変更するとき(DDL発行時)に トランザクションで保護できない場合がある • インデックス戦略がアドホックになりがち • データ種別の数だけテーブルが増える ラーメン屋リスト 店名 住所 評価 …
  23. 23. モデル写像アプローチ • データのモデルをRDBMS上に構築する • メタプログラミング的 • メリット • RDBMSのテーブル定義変更が不要 • ロックの粒度を小さくできる • デメリット • パフォーマンスはあまりよくない • レコード数が非常に多くなる • よいインデックスを張るのが難しい データテーブル テーブル カラム 番号 データ ラーメン屋リスト 店名 ラーメン屋リスト 住所 ラーメン屋リスト 評価 ラーメン屋リスト … 1 1 1 1 ラーメン屋リスト 店名 ラーメン屋リスト 住所 ラーメン屋リスト 評価 ラーメン屋リスト … 2 2 2 2
  24. 24. salesforceアプローチ • 汎用的で巨大な構造を最初に定義 • 最初に100カラムとか用意しておく • 検索用にインデックステーブル • メリット • RDBMSのテーブル定義変更が不要 • わかりやすい • デメリット • 項目数に上限がある データテーブル テーブル 番号 C1 C2 C3 C4 C5 … ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … インデックステーブル テーブル 番号 インデックス値 × データ型の数だけ 1 2 3 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3
  25. 25. friendfeedアプローチ • データをシリアライズして 1カラムに放り込む • JSONみたいなイメージ • 検索用にインデックステーブル • メリット • RDBMSのテーブル定義変更が不要 • Salesforceアプローチに比べて項目数 の制限が無い • デメリット • データ更新やシリアライズ・デシリアラ イズのコストが大きい データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} { …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 × データ型の数だけ ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3
  26. 26. kintoneはどのアプローチ? friendfeedアプローチ ちなみに命名元のfriendfeedというサービスは、今はもうない
  27. 27. こんな形の普通のテーブルだったら どうやってデータを絞り込むの? ラーメン屋リスト 店名 住所 評価 … 天一 S …
  28. 28. SQLで書くとこんな感じ SELECT * FROM ラーメン屋リスト WHERE 店名='天一' AND 評価='S'
  29. 29. {天一 S friendfeedアプローチだとこうなる データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 天一 S
  30. 30. {天一 S 店名が '天一' データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 天一 S
  31. 31. {天一 S 店名が '天一' かつ評価が 'S' データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 天一 S
  32. 32. {天一 S 店名が '天一' かつ評価が 'S' データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 天一 S 番号=3のレコードが 目的のレコードであることがわかる
  33. 33. {天一 S 店名が '天一' かつ評価が 'S' データテーブル テーブル 番号 データ ラーメン屋リスト ラーメン屋リスト ラーメン屋リスト … { …} { …} …} 1 2 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 インデックステーブル テーブル 番号 インデックス値 ラーメン屋リスト 1 ラーメン屋リスト 2 ラーメン屋リスト 3 天一 S 番号=3のレコードを取得する
  34. 34. SQLで書くとこんな感じ SELECT データ FROM データテーブル JOIN ●インデックステーブル ON データテーブル.テーブル=●インデックステーブル.テーブル AND データテーブル.番号=●インデックステーブル.番号 JOIN ●インデックステーブル ON データテーブル.テーブル=●インデックステーブル.テーブル AND データテーブル.番号=●インデックステーブル.番号 WHERE データテーブル.テーブル = 'ラーメン屋リスト' AND ●.インデックス値 = '天一' AND ●.インデックス値 = 'S'
  35. 35. それって結構大変じゃない? そう、大変。(SQLもパフォーマンスも…) けど大丈夫! kintoneは業務システムなのでデータ量は 多くとも数万件のオーダーで済むという前提があった☺ < 我々は非機能要件で保護されている!
  36. 36. 前提の崩壊 うわー! 増 大 す る デ ー タ この話題は後半に続く
  37. 37. kintone の絞り込み
  38. 38. kintone から業務データを絞り込む RDBMS 業務データを 絞り込もう 何をしている?
  39. 39. UI : 絞り込み画面
  40. 40. UI : REST API SQLライクな独自クエリで条件指定して問い合わせる。 (絞り込み画面もブラウザ側で独自クエリを組み立てて送信) GET /k/v1/records.json ?app=1 &query=部署 in ("営業", "マーケティング") and 営業内容 like "引き合い"
  41. 41. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON
  42. 42. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON • 構文解析
  43. 43. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 • 暗黙的な条件追加 • 条件式最適化 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON
  44. 44. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 • SQLに変換する • さっきのJOINおばけを作る 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON
  45. 45. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON • 条件に合う レコードのIDを取得 • レコードのデータを取得
  46. 46. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON • オブジェクト変換
  47. 47. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON • アクセス権評価
  48. 48. kintone の絞り込みの仕組み 送信 AST (抽象構文木) 変換独自クエリ SQL変換 実行 結果セット (生データ) 結果セット (オブジェクト) 変換変換 返却返却 JSON • JSON変換
  49. 49. 補足:AST(抽象構文木)とは? • プログラム(ここでは独自クエリ)を木構造に変換したもの。 AND IN LIKE 部署 営業内容 営業 引き合い マーケティング 部署 in ("営業", "マーケティング") and 営業内容 like "引き合い"
  50. 50. ASTに変換するメリット • 不正な入力を構文エラーとして検出できる。 • 安全に書き換えやすい。 • 文字列置換で内部でクエリを書き換え→キビシイ🙅 • SQLから独立しているため ASTからほかの問い合わせ言語に置き換えることも。 • これは後半の伏線
  51. 51. パフォーマンス問題
  52. 52. ✋注意✋ ここからのお話は、開発中のものです。 弊社サービス kintone に (まだ)反映されていません。
  53. 53. 先ほどの続き うわー! 増 大 す る デ ー タ
  54. 54. 湧き上がる問題 • データを絞り込んでも、何分も結果が返ってこない • 絞り込みのためのSQLが読みにくく、チューニングが大変 • チューニングのためにさらにSQLが膨れ上がったり パフォーマンスと保守性の低下。
  55. 55. インデックス テーブル インデックス テーブル どこを直せばいい? いままではこう。 ②+③が遅く複雑なSQLになっている。 データテーブル インデックス テーブル① ④ ③ ② 検索するぞ!
  56. 56. インデックス テーブル インデックス テーブル ボトルネックを潰すしかない ②に当たる部分を高速化するんだ! データテーブル インデックス テーブル① ④ ③ ② 遅いぞ! なにくそ!
  57. 57. どうやればいいだろう? 問題点はJOINが大量にあること • JOINしないように検索対象のテーブルをまとめたい • まとめるとインデックスがうまく張れない • ≒構造写像アプローチのデメリット • データ量が膨大だとRDBMSでは 全項目のインデクシングは困難
  58. 58. Elasticsearch • Elasticsearchとはなに? • 様々なユースケースを解決する、 分散型RESTful検索/分析エンジンです。(本家サイトより)
  59. 59. Elasticsearchのいいところ • 分散型 • 複数のノードからクラスターを構成する • ノードを増やして性能を上げることが出来る Cluster Node Node Node Node …
  60. 60. Elasticsearchのいいところ • スキーマ(Mapping)を定義することができる • スキーマをもとにした検索ができる Index Type 番号 店名 住所 評価 … Type 名前 性別 年齢 趣味 地域 … …
  61. 61. Elasticsearchのいいところ • 全文検索ができる • キーワード検索をおこなうことができる • 'トンドル' で検索して '㌧㌦' も候補にあげることもできる • すでにkintoneは全文検索エンジンのSolrも組み合わせて 使っており、それの置き換えにもElasticsearchを検討していた
  62. 62. Elasticsearchのいいところ • 安定運用やセキュリティに力を入れている • Java Security Manager • 一部のモジュールだけに特権を制限している • JarHell対策 • ライブラリやクラスの衝突により、実行時に誤動作すること • Elasticsearchは起動時に衝突していないか検証している • 起動時チェック • ヒープサイズ・ファイルデスクリプタ・仮想メモリが十分か確認 • などなど、詳細はここをチェック! • https://www.elastic.co/jp/blog/elasticsearch-the-server
  63. 63. でてきた解決策 • 絞り込みはElasticsearchにまかせて RDBMSはオリジナルデータの保存場所とする • 堅牢さはRDBMSに一日の長がある • ID指定によるデータ取得は 現状RDBMSでも遅くない
  64. 64. 新しいアーキテクチャ ① ④ データテーブル ③ インデックス ② 同 期
  65. 65. 新しいアーキテクチャ 送信 変換独自クエリ IDリスト • QueryDSL(Elasticsearchのクエリ言語) に変換する。 結果セット (生データ) 結果セット (オブジェクト) 変換変換返却 JSON QueryDSL AST (抽象構文木) 実行 返却
  66. 66. 新しいアーキテクチャ 送信 変換独自クエリ IDリスト • 条件に合う レコードのIDを取得 結果セット (生データ) 結果セット (オブジェクト) 変換変換返却 JSON QueryDSL AST (抽象構文木) 実行 返却
  67. 67. 新しいアーキテクチャ 送信 変換独自クエリ IDリスト • レコードのデータを取得 結果セット (生データ) 結果セット (オブジェクト) 変換変換返却 JSON QueryDSL AST (抽象構文木) 実行 返却
  68. 68. 発生するトレードオフ • インデックスの更新が非同期 • RDBMS上のデータをもとにインデックスを更新するため トランザクションが同一ではない。 なのでElasticsearchが絞り込みで返した値と RDBMSに入っているデータにズレが 発生する時間がある ① ④ データテーブル ③ インデックス ② 同 期
  69. 69. 対策 • 同期が遅延しているかどうかを管理し、 遅延が発生している状況下では、 間違った絞り込み結果を返してないか プログラム側で再フィルタリングを行う ① ④ データテーブル ③ インデックス ② 同 期 遅延が発生してるな? 俺もフィルタリングや
  70. 70. ベンチマーク結果 • 2,000万件のレコードを 絞り込む時間がいまの実装に 比べて大幅に短縮できた! ※ kintoneの絞り込みが改善できるかどうかという 観点で行ったベンチマークなので RDBMSとElasticsearchの機材スペック差 などは公平ではありません
  71. 71. まとめ • スキーマ不定なデータをRDBMSで扱う際の 主要なアーキテクチャを4つ紹介! • kintoneではfriendfeedアプローチを採用してるよ • このアプローチは大量データに向かない☹ • kintoneの絞り込みのアーキテクチャ紹介 • 独自クエリとRDBMSとの橋渡し • Elasticsearchという分析エンジンを活用して 絞り込みを速くするアーキテクチャに置き換えたよ☺ • トレードオフがあり、それについては受け入れられる レベルまでアプリケーションでフォローをしたよ
  72. 72. おしまい やってやれないことはない 増 大 す る デ ー タ

×