スマイルゼミの裏側(db編)

Post on 16-Apr-2017

661 Views

Category:

Engineering

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

© 2016 JustSystems Corporation.

スマイルゼミの裏側~データベース編~

(株)ジャストシステムILS 事業部開発部

菅井友之

© 2016 JustSystems Corporation.

• スマイルゼミ中学生コース– サーバー担当

• スマイルゼミ小学生コース、中学生コースの立ち上げ– サーバー主担当として参加

• 主に Tomcat 上で動いて PostgreSQL を使うアプリケーションをやっています。

自己紹介

© 2016 JustSystems Corporation.

スマイルゼミでやらかしてしまった話

( DB 的な意味で)

© 2016 JustSystems Corporation.

スマイルゼミでやらかしてしまった話

( DB 的な意味で)PostgreSQL 9.3

© 2016 JustSystems Corporation.

その前に

© 2016 JustSystems Corporation.

スマイルゼミご存じですか?

© 2016 JustSystems Corporation.

• 小中学生向けの家庭学習サービス• すべての学習がタブレット上で完結できる日本初のサー

ビス• 小中一貫で学べる唯一のタブレット教材

© 2016 JustSystems Corporation.

facebook やってます

https://www.facebook.com/smile.zemi/

© 2016 JustSystems Corporation.

小学生 中学生

ある一週間のアクセス状況

© 2016 JustSystems Corporation.

• 小中学生向けのサービス• ユーザーは、日中学校に行っている

小学生 中学生

ある一週間のアクセス状況

© 2016 JustSystems Corporation.

• 小中学生向けのサービス• ユーザーは、日中学校に行っている

平常時、日中の負荷は低い

小学生 中学生

© 2016 JustSystems Corporation.

_人人人人人人人人人_> 突然の負荷上昇 < ̄Y^Y^Y^Y^Y^Y^Y^Y ̄

© 2016 JustSystems Corporation.

• 中学生 DB の朝の負荷であり、垂直に立ち上がっているので、バッチ処理

• グラフが変わる前の日に、 hotfix がリリースされている。• 調べてみると、 course_results で 1300 万行の seq.scan が大量

に発生している。

© 2016 JustSystems Corporation.

CREATE VIEW AS study_log_memorycard_view (   WITH memorycard_info AS (     SELECT ...   FROM course_results cr      JOIN course_master cm ON cr.course_id AND          cm.memory_card_info IS NOT NULL)   (SELECT ...   FROM memorycard_set_results msr              JOIN memorycard_info ...            WHERE ...)   UNION ALL   (SELECT ... FROM memorycard_set_results msr              JOIN ... JOIN memorycard_info ...            WHERE ...    ))

© 2016 JustSystems Corporation.

• 処理の内容は変えずに、 view を使うようにプログラムを変更していた。

© 2016 JustSystems Corporation.

• 処理の内容は変えずに、 view を使うようにプログラムを変更していた。

• view を使わずに処理する場合には、オプティマイザが後続の WHERE を先に処理してくれていたのだろう

© 2016 JustSystems Corporation.

• 処理の内容は変えずに、 view を使うようにプログラムを変更していた。

• view を使わずに処理する場合には、オプティマイザが後続の WHERE を先に処理してくれていたのだろう

• view を使ってしまったために、 course_results が絞り込まれずに含まれてしまう。

© 2016 JustSystems Corporation.

CREATE VIEW AS study_log_memorycard_view (   WITH memorycard_info AS (     SELECT ...   FROM course_results cr      JOIN course_master cm ON cr.course_id AND          cm.memory_card_info IS NOT NULL)   (SELECT ...   FROM memorycard_set_results msr              JOIN memorycard_info ...            WHERE ...)   UNION ALL   (SELECT ... FROM memorycard_set_results msr              JOIN ... JOIN memorycard_info ...            WHERE ...    ))

© 2016 JustSystems Corporation.

• 処理の内容は変えずに、 view を使うようにプログラムを変更していた。

• view を使わずに処理する場合には、オプティマイザが後続の WHERE を先に処理してくれていたのだろう

• view を使ってしまったために、 course_results が絞り込まれずに含まれてしまう。

• さらに、ユーザーごとに view に対するSELECT をしている。– 長時間の高負荷状態に

© 2016 JustSystems Corporation.

対策

© 2016 JustSystems Corporation.

• 前日の学習結果を集計する処理なので、 view 定義の段階で学習日で絞り込むことにした

• view 定義の各 SELECT 文に以下の絞り込み条件を追加

対策

© 2016 JustSystems Corporation.

• 前日の学習結果を集計する処理なので、 view 定義の段階で学習日で絞り込むことにした

• view 定義の各 SELECT 文に以下の絞り込み条件を追加

対策

study_end > (now() - '2 days'::interval)

© 2016 JustSystems Corporation.

• 前日の学習結果を集計する処理なので、 view 定義の段階で学習日で絞り込むことにした

• view 定義の各 SELECT 文に以下の絞り込み条件を追加

• 幸い、他の処理では使っていない view だったので、同名のまますぐに定義変更できた。

対策

study_end > (now() - '2 days'::interval)

© 2016 JustSystems Corporation.

© 2016 JustSystems Corporation.

他の事例

© 2016 JustSystems Corporation.

2013 年 12 月小学生向けみまもるトーク

拡張され続けるサービス

© 2016 JustSystems Corporation.

2013 年 12 月小学生向けみまもるトーク

拡張され続けるサービス

2014 年 11 月中学生向けみまもるトーク

© 2016 JustSystems Corporation.

小学生向けに作ったトーク機能に、中学生を参加させる

© 2016 JustSystems Corporation.

• あるトークグループに参加しているユーザー( talker )の一覧を取得する SQL 文

• - talker は、親、小学生、中学生、その他(親が招待した人)があり、それぞれ別体系の id で管理されている。

SELECT talkers.* FROM talkers LEFT OUTER JOIN accounts ON talkers.account_id = accounts.idWHERE (((accounts.parent_id = xxxxxxxx OR child_id = xxxxxxxx ) OR jh_child_id = xxxxxxxx ) OR account_id = xxxxxxxx )

© 2016 JustSystems Corporation.

• 中学生が増えたのでこの条件が増えた• OR 条件が追加されたことにより、実行計

画がくるってしまって、 Seq Scan on accounts 、 Seq Scan on talkers が発生

• index はあるのに使ってもらえない。

OR jh_child_id = xxxxxxxx

© 2016 JustSystems Corporation.

対策

© 2016 JustSystems Corporation.

対策SELECT talkers.* FROM talkers LEFT OUTER JOIN accounts ON talkers.account_id = accounts.id WHERE (accounts.parent_id = xxxxxxxx)UNIONSELECT talkers.* FROM talkers WHERE (child_id = xxxxxxxx)UNIONSELECT talkers.* FROM talkers WHERE (jh_child_id = xxxxxxxx )UNIONSELECT talkers.* FROM talkers WHERE (account_id = xxxxxxxx ) ORDER BY id;

© 2016 JustSystems Corporation.

• Index scan ですむ単純 SQL にして結果を UNION すると 1000-10000 倍速になった!

– (というよりは、ロジック変更で 1000 倍遅くなっていた)

対策SELECT talkers.* FROM talkers LEFT OUTER JOIN accounts ON talkers.account_id = accounts.id WHERE (accounts.parent_id = xxxxxxxx)UNIONSELECT talkers.* FROM talkers WHERE (child_id = xxxxxxxx)UNIONSELECT talkers.* FROM talkers WHERE (jh_child_id = xxxxxxxx )UNIONSELECT talkers.* FROM talkers WHERE (account_id = xxxxxxxx ) ORDER BY id;

© 2016 JustSystems Corporation.

• UNION が あるところを変更するときは慎重に– UNION していいのは、中間処理結果が十分

に小さいとわかっている場合のみ。– 特に view の中で UNION するのは危険

• 中間テーブルが十分に小さく、素早く、作れるところでは UNION はとても有効!

まとめ

© 2016 JustSystems Corporation.

スマイルゼミを一緒に育てる人、募集しています。

top related