26
遅いクエリと向き合う仕組み サイボウズ株式会社 ⾚井 駿平 1

遅いクエリと向き合う仕組み #CybozuMeetup

  • Upload
    s-akai

  • View
    8.090

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 遅いクエリと向き合う仕組み #CybozuMeetup

遅いクエリと向き合う仕組みサイボウズ株式会社⾚井 駿平

1

Page 2: 遅いクエリと向き合う仕組み #CybozuMeetup

whoami

▌⾚井 駿平l 2013年4⽉⼊社l アプリケーション基盤チーム所属l プログラミング⾔語の研究→博⼠号取得→サイボウズ

▌ミドルウェアからWebアプリまでl 副業では個⼈でiOSアプリを作ってます

2

Page 3: 遅いクエリと向き合う仕組み #CybozuMeetup

アプリケーション基盤チーム

▌サイボウズ内の複数の製品で使うプログラムを作るチームl ミドルウェア

l メッセージキュー、全⽂検索、サムネイル作成、ログ…l Webアプリ

l ユーザー管理機能、プロフィール表⽰…l Webアプリのライブラリ、フレームワーク

l Javaで作ってる製品l 選定したり、作成したり

3

Page 4: 遅いクエリと向き合う仕組み #CybozuMeetup

今⽇話すこと

▌ライブラリを作った話l データベース周り

l 障害を減らす仕組みl パフォーマンスを改善するためのORマッパー

4

Page 5: 遅いクエリと向き合う仕組み #CybozuMeetup

kintoneの話

5

Page 6: 遅いクエリと向き合う仕組み #CybozuMeetup

kintone?

▌Webでデータベースを作れるようなサービスl ドラッグ&ドロップで⼊⼒フォームとデータベースが作れるl SQLでのtable ≒ アプリ

l ただし、スキーマがどんどん変わるl ドキュメント指向データベースっぽい

6

Page 7: 遅いクエリと向き合う仕組み #CybozuMeetup

7

Page 8: 遅いクエリと向き合う仕組み #CybozuMeetup

8

Page 9: 遅いクエリと向き合う仕組み #CybozuMeetup

kintoneの中⾝のはなし

▌永続化にはRDBMS (MySQL) を使っているl 1アプリ=1table ではないl 固定のtableに⾊々な形のアプリがマッピングされるl 複雑なクエリが多く発⾏される場合が…

l 複雑な条件での絞込l パフォーマンスが…

▌詳しくは「kintoneの検索⾼速化への取り組み」を参照l https://www.slideshare.net/RyoMitoma/kintone-73674134

9

Page 10: 遅いクエリと向き合う仕組み #CybozuMeetup

複雑なクエリで障害が

▌複雑な絞り込みが⾏われるとリクエストに⼗分単位で時間が掛かる場合がl DBが遅い/⼤量のクエリ/⼤量のメモリ

▌ロードバランサーでは5分以上掛かるリクエストは強制切断しているl アプリケーションサーバー側ではリクエストは⽣き続けるl リロードされると…

10

Page 11: 遅いクエリと向き合う仕組み #CybozuMeetup

どうしたものか

▌ クエリ⾃体を改善するl 当然必要l kintoneの性質上、遅いクエリはどうしても発⽣し得る

l 起きちゃった場合の対応をしないといけない▌ クエリのタイムアウト

l MySQL 5.7ではSELECTのタイムアウトが出来るl 当時使ってたのは5.6…l kintoneではそこそこ遅いクエリが多く⾛る

l 使えない▌ 遅すぎるリクエストのみを強制的に終了させたい

l JavaのServlet上で動いているのでkillとか出来ない11

Page 12: 遅いクエリと向き合う仕組み #CybozuMeetup

リクエストが⾃分で終了すればいい

12

▌リクエストの中のチェックポイントで経過時間を判定l 超えていたら例外を投げて終了

▌コード中のあらゆる場所に判定するコードを書く?l 量が多くて⼤変l コードが汚くなるl 漏れが発⽣する

Page 13: 遅いクエリと向き合う仕組み #CybozuMeetup

よし、アスペクト指向だ!

▌アスペクト指向プログラミング(AOP)l プログラミングの⾊々な場所に処理を挿⼊出来る技術l リフレクションの凄いやつl JavaのWebフレームワークには⼊ってたりする

l あまり流⾏らなかったけど

▌データベースにアクセスするたびに経過時間をチェックする

13

Page 14: 遅いクエリと向き合う仕組み #CybozuMeetup

aspectの例

14

public class RepositoryAspect {@Pointcut("execution(public * com.cybozu.Repository+.*(..))") void timeoutTarget() { }

@After(value = "timeoutTarget()") public void after() {

DateTime expire = ((DateTime) request.getAttribute(“expire”));

if (expire != null && expire.isBeforeNow()) {throw new RequestTimeoutException();

}}

}

DBにアクセス全てのメソッド

を実⾏した後で以下の処理を実⾏す

Page 15: 遅いクエリと向き合う仕組み #CybozuMeetup

効果は?

▌とある1⽇にタイムアウトしてたリクエストは90件くらいl 致命的な障害は防げてそう

▌タイムアウトしたログを頼りにクエリを改善していけるかも

15

Page 16: 遅いクエリと向き合う仕組み #CybozuMeetup

ORマッパーを乗り換える

16

Page 17: 遅いクエリと向き合う仕組み #CybozuMeetup

S2Dao

▌kintone等ではS2Dao/Seasar2を使ってましたl アノテーションでクエリを書くと、メソッドが⾃動⽣成

17

@S2Dao(bean = User.class)public interface UserDao {@Query(“SELECT * FROM user WHERE id = /*id*/”)List<User> getById(Long id);

}

Page 18: 遅いクエリと向き合う仕組み #CybozuMeetup

ORマッパーがEOL!?

▌S2DaoがEOLになりそう! 移⾏しないと▌Spring Data JPA + Hibernate に移⾏しましたl S2Daoと同じようにアノテーションで書けるl JPAという標準だl JPAの中ではHibernateがメジャー?

18

Page 19: 遅いクエリと向き合う仕組み #CybozuMeetup

⼤失敗19

Page 20: 遅いクエリと向き合う仕組み #CybozuMeetup

パフォーマンスが出ませんでした

▌制御できないキャッシュl kintone では可変⻑の巨⼤なIN句が使われていたl それぞれの⻑さでクエリがキャッシュ

l メモリを圧迫してGC多発l 他にも性能問題がぽろぽろと

▌詳しくはブログにl 「我々はいかにして技術選択を間違えたのか? 2016」l http://blog.cybozu.io/entry/2016/12/28/101500

20

Page 21: 遅いクエリと向き合う仕組み #CybozuMeetup

Hibernateをやめたい

▌よい乗り換え先ある?l 他のJPA実装?

l 仕組み上あまりかわらなそうl MyBatis?

l IN句を使うのにforeach⽂みたいなのを書かないといけないl SpringのJdbcTemplate

l 書き⽅が⼤きく変わるl jdbcTemplate.query(“SELECT * FROM user”, rowMapper)

▌困った困った21

Page 22: 遅いクエリと向き合う仕組み #CybozuMeetup

⾃分で作っちゃえ

▌JdbcTemplateをSpring Dataでラップするものを作るl 何故か誰も作ってないっぽい

▌コンセプトl 今までと同じようにアノテーションで書けるl 余計なことはしないシンプルなラッパー

l has-many has-one等すらサポートしない

22

Page 23: 遅いクエリと向き合う仕組み #CybozuMeetup

コードの例

▌S2DaoやSpring Data JPAと⼤体同じように書ける

23

@Table(name = “user”)class User {

@Id@GeneratedValuepublic Long id;

@Column(“login_name”)public String loginName;

}

@Repositorypublic interface UserRepository extends JdbcTemplateRepository<User> {@Query(“SELECT * FROM user WHERE id=:id”)List<User> getById(@Param(“id”) Long id);

}

Page 24: 遅いクエリと向き合う仕組み #CybozuMeetup

切り替えた結果

▌kintoneで全⾯的に乗り換えてから約1ヶ⽉l 今のところクエリ関係が原因の障害は起きてなさそうl 社内独⾃の性能測定では、10%ほど性能が向上した

24

Page 25: 遅いクエリと向き合う仕組み #CybozuMeetup

オープンソース化します

▌Spring Data Jdbc Templatel https://github.com/cybozu/spring-data-jdbc-template

▌まだソースのみl maven等に上げるのはこれから検討

▌もうすこし詳しい話はブログに書くかも

25

Page 26: 遅いクエリと向き合う仕組み #CybozuMeetup

まとめ

▌アプリケーション基盤チームでは社内のライブラリの整備もしています

▌ものによってはオープンソース化もします

26