Slide 1

Slide 1 text

FlyleでのDBとの堅牢な付き合い方と パフォーマンス改善への取り組み 株式会社フライル: 吉澤直哉

Slide 2

Slide 2 text

自己紹介 ・ふそやん azihsoyn@twitter ・釣り好き ・お酒とアニメが好き ・rehash.fmというポッドキャストをやってました  (しばらく休止中のため過去形 ) ・フライルには2022年9月に入社

Slide 3

Slide 3 text

会社紹介

Slide 4

Slide 4 text

Flyleとは 詳細はこちら(https:/ /flyle.io/jp) 3
 1
 2
 多様な経路の
 顧客フィードバックを集約 
 顧客データを活かした 
 製品開発の意思決定を支援 
 プロダクトマネジメントの 
 立ち上げをサポート 
 多様な経路の
 顧客の声の集約・連携
 NPS等のサーベイ 
 AIによる自動分類 
 (開発中)
 優先度づけ
 ロードマップ
 顧客が求める機能を分析
 組織立ち上げサポート
 ツールの使い方の 
 サポート
 プロダクトマネジメント 
 研修の実施 
 複雑なプロダクトマネジメント業務を効率化する多様な機能を揃えています。直近ではNPSなどのサーベイ機能をリリー ス。今後は、AIによる自動分類・分析機能を大きく強化予定。


Slide 5

Slide 5 text

各職種募集中です! https://herp.careers/v1/flyle

Slide 6

Slide 6 text

Flyleのバックエンド環境 ・SpringBoot 2.7でHibernate 5 ・RDS MySQL 8.0.29

Slide 7

Slide 7 text

Flyleのバックエンド環境 ・SpringBoot 2.7でHibernate 5  (SpringBoot3出ましたね) ・RDS MySQL 8.0.29  (MySQL 8.0.32出ましたね)

Slide 8

Slide 8 text

堅牢にするために

Slide 9

Slide 9 text

MySQLのCHECK制約を使う ・IDフィールドの桁数チェック ・textカラムの空文字を除外して nullに統一 ・使える文字の制限 など kotlin関係ないですが...

Slide 10

Slide 10 text

チェック制約の例

Slide 11

Slide 11 text

チェック制約の挙動

Slide 12

Slide 12 text

堅牢にするために

Slide 13

Slide 13 text

ドメイン型

Slide 14

Slide 14 text

ドメイン型とは こんなやつ 参考: https://www.postgresql.jp/document/12/html/domains.html

Slide 15

Slide 15 text

不正な値の混入を防げる

Slide 16

Slide 16 text

ドメイン型のバリデーション initで変なデータが入らないようにチェックしてる

Slide 17

Slide 17 text

init時にバリデーションを実行

Slide 18

Slide 18 text

引数の取り違えを防げる😊

Slide 19

Slide 19 text

ドメイン型を使ったJPARepositoryのinterface

Slide 20

Slide 20 text

ドメイン型の課題 そのままではHibernateで使えない

Slide 21

Slide 21 text

解決策: カスタムコンバーターを書く

Slide 22

Slide 22 text

カスタムコンバーターの課題 ドメイン型が増える度にカスタムコンバーターを書く手 間...

Slide 23

Slide 23 text

解決策: KSPで自動生成しよう!

Slide 24

Slide 24 text

KSPとは KSP(Kotlin Symbol Processing)は、Kotlinコンパイラの拡張機能であり、 Kotlinのコンパイル時に、コンパイル されたコードにアノテーションベースの処理を追加することができます。 KSPを使用することで、Kotlinのコード ジェネレーションを簡素化し、自動化することができます。 KSPは、Dagger HiltやRoomなどのライブラリーでも 使用されており、Kotlinプロジェクトの開発を効率化するための貴重なツールの 1つです。 By ChatGPT https://kotlinlang.org/docs/ksp-overview.html

Slide 25

Slide 25 text

KSPのイメージ

Slide 26

Slide 26 text

KSPによって自動生成された コンバーターたち(の一部)

Slide 27

Slide 27 text

ドメイン型とカスタムコンバーターの課題 nativeQuery内では使えない...

Slide 28

Slide 28 text

nativeQueryとは JPARepositoryの命名では表現しきれない複雑な SQLを直接書ける

Slide 29

Slide 29 text

解決策: nativeQuery内ではメソッドが使える!

Slide 30

Slide 30 text

Listも対応可能(ややトリッキー)

Slide 31

Slide 31 text

さらに堅牢にするために nativeQuery内のtypoなどをチェックできるように Repositoryのメソッドが実行可能かを全件テストして る

Slide 32

Slide 32 text

堅牢にするために

Slide 33

Slide 33 text

Enum型

Slide 34

Slide 34 text

Enum型 Enumな値はテーブルで管理

Slide 35

Slide 35 text

Enum型 Enumな値はテーブルで管理

Slide 36

Slide 36 text

Enum型 Kotlinのコード

Slide 37

Slide 37 text

Enum型の課題 DBの値とKotlinのコードが乖離する

Slide 38

Slide 38 text

対策: 起動時にSELECTしてチェック

Slide 39

Slide 39 text

パフォーマンス問題

Slide 40

Slide 40 text

ある時 データを10000件CSVでエクスポートしたい → SELECTしたものを返すだけだから余裕余裕 😆 → API Timeout(15秒) → 😱

Slide 41

Slide 41 text

考えられる原因 ・無駄にレコードを取得しているのでは? ・indexが効いてないのでは? ・トランザクションのロックかかってる? ・N+1になってないか? ・ドメイン型のinitのバリデーション(正規表現)が重い? ・そもそもHibernateが遅い?

Slide 42

Slide 42 text

考えられる原因 ・無駄にレコードを取得しているのでは? → ❌ ・indexが効いてないのでは?→ ❌ ・トランザクションのロックかかってる? → ❌ ・N+1になってないか?→ ❌ ・ドメイン型のinitのバリデーション(正規表現)が重い?→ ❌ ・そもそもHibernateが遅い? →😇

Slide 43

Slide 43 text

全部違った

Slide 44

Slide 44 text

原因 独自の型をカスタムコンバーターで変換する場合、 その型はSerializableである必要がある By ChatGPT

Slide 45

Slide 45 text

修正(1行のみ)

Slide 46

Slide 46 text

10000件のSELECTに15秒以上かかっていたのが1秒ぐらい まで短縮🎉

Slide 47

Slide 47 text

まとめ ・MySQLのチェック制約を積極的に使う ・IDフィールドにドメイン型を使うことで堅牢なインターフェースに ・Enumはテーブルで管理 ・KSPを使って自動でカスタムコンバーターを生成 ・nativeQuery内では引数のメソッドを使える ・ドメイン型はSerializableに