Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
MySQLで2億件のシリアルデータと
格闘したチューニングの話
YAPC::Asia Tokyo 2015
Kenji Saito / @saiken3110
自己紹介
・斉藤 健二 Kenji Saito
・@saiken3110
・Java PHP Perl
・Oracle MySQL
今日の内容
MySQLで
2億件のシリアルデータを
つかった話
主にチューニングの話です。
Perlも最後にちょっとでてきます。。
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・まとめ
システムの概要(フロント)
商品購入
シリアル入力
入力
・商品A
・サイズ
商品サイズ選択
登録
XXL ▼
商品シリアル
紐付
利用履歴
システムの概要(バックエンド)
シリアルマスタ
商品名
シリアル数
商品・シリアル紐付け
紐付け
▼
商品シリアル
紐付
2億件!! 1億件!!
・Red Hat 5.6
・Perl 5.20
・MySQL 5.6
DBサーバのインフラ事情①
・CPU 2コア
・メモリ 8G
・ディスク 450G
・/tmp 2G
DBサーバのインフラ事情②
→ 2コア、8G。。。2億件。。。
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・まとめ
□対象テーブル
・シリアルマスタ(2億件)
・商品シリアル紐付(1億件)
□内容
・インデックスを使った検索
・プライマリーキーでの検索
・フルスキャンでの検索
・フルスキャンでのcount
・フルスキャンでのorder by
・insert
...
いろいろと問題が・・・
○count に84秒、CPUを80 ~ 95 %使用
→ アプリケーションからは
実行しないため、対応不要とした
○order by や alter で/tmp が枯渇
→ tmp_dir を物理ディスクに変更
→ エラーがでなくなったが、
...
○商品シリアル紐付のデータファイルが28Gに。。
→ パフォーマンスのために、
各レコードで商品情報を持っていたのをやめた
→ 管理用のTBLを作り、
正規化、15G に縮小!
○insertが意外と早い
「LOAD DATA」で3億件の登録が...
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・まとめ
2億件登録したときの話①
シリアルマスタ
商品名
シリアル数
商品・シリアル紐付け
紐付け
▼
商品シリアル
紐付
2億件!! 1億件!!
ココ
負荷テストのときに、3億件が70分で登録できた
実際のデータで2億件登録しようとしたら、、
75時間かかった。。
2億件登録したときの話②
□実行時間の推移
2億件登録したときの話③
※500万件ずつ「LODA DATA」で登録
8000万件から
急激に遅延
□負荷テストのときより遅くなった原因
→ 負荷テストのときはシリアルが連番
実際は、ランダムな数字
→ insert 時にindex の再作成が発生!
□8000万件くらいから急激に遅くなった原因
→ innodb_buffer_pool が枯...
innodb_buffer_pool とinsert①
さすがに75時間を何度もは無理なので、
innodb_buffer_pool_size を10分の1くらいで
試してみた
40時間くらいかけて。。
innodb_buffer_pool とinsert②
innodb_buffer_pool_size を1G、500M、250Mで
10万件のinsert × 100回にかかる時間を計測
250M で実行した場合、
340万件から遅延が発生
...
innodb_buffer_pool とinsert③
データ量(登録件数)が増加し、
innodb_buffer_pool が枯渇すると、
insert が大幅に遅延し始める。
→ メモリからあふれて、
ディスクI/Oが発生しているため。
→...
ついでに、、
主キーがシーケンスなら
インデックスの再構築が
早いんじゃないかと思った
試してみた
再びの40時間。。
主キーとinsert①
主キーをシリアル(ランダムな数字)から
シーケンスに変更して、2億件の登録にかかる時間を比較
○変更前
・主キー:シリアル
・ユニークキー:シーケンス
○変更後
・主キー:シーケンス
・ユニークキー:シリアル
主キーとinsert②
○2億件の登録にかかった時間
75時間 → 30時間に改善!
→ 主キーが連番になったことで、
主キーのインデックス構築にかかる時間が減少
変更前は2億件の登録に
約75時間
変更後は2億件の登録が
約30時間で完了
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・その他 Perlのチューニング
・まとめ
updateではまった話①
シリアルマスタ
商品名
シリアル数
商品・シリアル紐付け
紐付け
▼
商品シリアル
紐付
2億件!! 1億件!!
ココ
負荷テストのときは、
100万件の紐付が74秒だった
お客さんの前でデモしたら、、
1時間かかった
updateではまった話②
updateではまった話③
□アプリケーションの動き
※1回のmaxが 100万件で1万件ごとにコミット
1)シリアルマスタからステータスが
「未使用」のものを取得
2)商品シリアル紐付へ、
入力した商品の情報をつけてシリアルをinsert
3...
updateではまった話④
□update が遅かった原因
→ update 時にindex の再構築が発生
→ シリアルがランダムなため、
紐付く主キーの読込みが重い。。
read_buffer_size (16k)ずつ
読み込まれる
紐付く...
updateではまった話⑤
□対応
ステータス管理をやめ、
管理テーブルを作成し、
update 自体を不要にした
→ 60分が45秒に改善!
→ インデックスの再構築怖い。。。
そんなこんなで、
なんとか無事リリースできました
よかった
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・その他 Perlのチューニング
・まとめ
今後の課題①
□増分バックアップ
現状mysqldump でフルバックアップ
→ 今後さらにデータが増えてくると、
バイナリログを使った
増分バックアップの方がよさそう
今後の課題②
□データ退避とかパーティショニング
→ 古いシリアルの退避とか、
できれば「xxxx_2015」とか作りたくないので、
うまくパーティションとか使えると。。
Topic
・システムの概要
・負荷テストした話
・2億件登録したときの話
・updateではまった話
・今後の課題
・その他 Perlのチューニング
・まとめ
その他 Perlのチューニング①
□コネクションプーリングっぽいこと
コネクションオブジェクトを
シングルトンにし、1worker 1コネクションを共有
→ コネクション生成のコストをなくした
その他 Perlのチューニング②
□マスタデータをキャッシュ
PSGIサーバ起動時に、メモリにDBのマスタデータを保持
→ worker 内でメモリは共有されるため、
DBアクセスが不要になる
※ただし、「Copy-On-Write」なので、
...
まとめ①
□innodb_buffer_pool_size は大きい方がいい
□主キーはシーケンスにした方がinsert が早い
□インデックスの再構築は意外とばかにならない
まとめ②
□負荷テスト大事
実際のデータに近いデータでやる
□結局計測してみないとわからないことは多い
→ 効果測定にすごく時間がかかるので、
負荷テストとかは、早めにやる
ありがとうございました!
Prochain SlideShare
Chargement dans…5
×

My sqlで2億件のシリアルデータと格闘した話

12 927 vues

Publié le

YAPC::Asia Tokyo2015 で発表させていただきました。
主にMySQLのチューニングの話です。
http://yapcasia.org/2015/talk/show/0af26fe4-0b7b-11e5-a29c-67dc7d574c3a

Publié dans : Technologie
  • Soyez le premier à commenter

My sqlで2億件のシリアルデータと格闘した話

  1. 1. MySQLで2億件のシリアルデータと 格闘したチューニングの話 YAPC::Asia Tokyo 2015 Kenji Saito / @saiken3110
  2. 2. 自己紹介 ・斉藤 健二 Kenji Saito ・@saiken3110 ・Java PHP Perl ・Oracle MySQL
  3. 3. 今日の内容
  4. 4. MySQLで 2億件のシリアルデータを つかった話
  5. 5. 主にチューニングの話です。 Perlも最後にちょっとでてきます。。
  6. 6. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・まとめ
  7. 7. システムの概要(フロント) 商品購入 シリアル入力 入力 ・商品A ・サイズ 商品サイズ選択 登録 XXL ▼ 商品シリアル 紐付 利用履歴
  8. 8. システムの概要(バックエンド) シリアルマスタ 商品名 シリアル数 商品・シリアル紐付け 紐付け ▼ 商品シリアル 紐付 2億件!! 1億件!!
  9. 9. ・Red Hat 5.6 ・Perl 5.20 ・MySQL 5.6 DBサーバのインフラ事情①
  10. 10. ・CPU 2コア ・メモリ 8G ・ディスク 450G ・/tmp 2G DBサーバのインフラ事情② → 2コア、8G。。。2億件。。。
  11. 11. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・まとめ
  12. 12. □対象テーブル ・シリアルマスタ(2億件) ・商品シリアル紐付(1億件) □内容 ・インデックスを使った検索 ・プライマリーキーでの検索 ・フルスキャンでの検索 ・フルスキャンでのcount ・フルスキャンでのorder by ・insert ・alter table (カラム追加) 負荷テスト
  13. 13. いろいろと問題が・・・
  14. 14. ○count に84秒、CPUを80 ~ 95 %使用 → アプリケーションからは 実行しないため、対応不要とした ○order by や alter で/tmp が枯渇 → tmp_dir を物理ディスクに変更 → エラーがでなくなったが、 50Gくらい一時領域を使ってた。。 → 運用で回避することにした 負荷テスト 結果① ERROR 3 (HY000) at line 1: Error writing file '/tmp/MY3p25s8' (Errcode: 28 - No space left on device)
  15. 15. ○商品シリアル紐付のデータファイルが28Gに。。 → パフォーマンスのために、 各レコードで商品情報を持っていたのをやめた → 管理用のTBLを作り、 正規化、15G に縮小! ○insertが意外と早い 「LOAD DATA」で3億件の登録が70分 → 後でいろいろ問題が発生。。 負荷テスト 結果②
  16. 16. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・まとめ
  17. 17. 2億件登録したときの話① シリアルマスタ 商品名 シリアル数 商品・シリアル紐付け 紐付け ▼ 商品シリアル 紐付 2億件!! 1億件!! ココ
  18. 18. 負荷テストのときに、3億件が70分で登録できた 実際のデータで2億件登録しようとしたら、、 75時間かかった。。 2億件登録したときの話②
  19. 19. □実行時間の推移 2億件登録したときの話③ ※500万件ずつ「LODA DATA」で登録 8000万件から 急激に遅延
  20. 20. □負荷テストのときより遅くなった原因 → 負荷テストのときはシリアルが連番 実際は、ランダムな数字 → insert 時にindex の再作成が発生! □8000万件くらいから急激に遅くなった原因 → innodb_buffer_pool が枯渇 → 検証してみた 2億件登録したときの話④
  21. 21. innodb_buffer_pool とinsert① さすがに75時間を何度もは無理なので、 innodb_buffer_pool_size を10分の1くらいで 試してみた 40時間くらいかけて。。
  22. 22. innodb_buffer_pool とinsert② innodb_buffer_pool_size を1G、500M、250Mで 10万件のinsert × 100回にかかる時間を計測 250M で実行した場合、 340万件から遅延が発生 500M で実行した場合、 700万件から遅延が発生
  23. 23. innodb_buffer_pool とinsert③ データ量(登録件数)が増加し、 innodb_buffer_pool が枯渇すると、 insert が大幅に遅延し始める。 → メモリからあふれて、 ディスクI/Oが発生しているため。 → メモリを増やすことで、 データ量が多くても遅延が発生しない
  24. 24. ついでに、、 主キーがシーケンスなら インデックスの再構築が 早いんじゃないかと思った 試してみた 再びの40時間。。
  25. 25. 主キーとinsert① 主キーをシリアル(ランダムな数字)から シーケンスに変更して、2億件の登録にかかる時間を比較 ○変更前 ・主キー:シリアル ・ユニークキー:シーケンス ○変更後 ・主キー:シーケンス ・ユニークキー:シリアル
  26. 26. 主キーとinsert② ○2億件の登録にかかった時間 75時間 → 30時間に改善! → 主キーが連番になったことで、 主キーのインデックス構築にかかる時間が減少 変更前は2億件の登録に 約75時間 変更後は2億件の登録が 約30時間で完了
  27. 27. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・その他 Perlのチューニング ・まとめ
  28. 28. updateではまった話① シリアルマスタ 商品名 シリアル数 商品・シリアル紐付け 紐付け ▼ 商品シリアル 紐付 2億件!! 1億件!! ココ
  29. 29. 負荷テストのときは、 100万件の紐付が74秒だった お客さんの前でデモしたら、、 1時間かかった updateではまった話②
  30. 30. updateではまった話③ □アプリケーションの動き ※1回のmaxが 100万件で1万件ごとにコミット 1)シリアルマスタからステータスが 「未使用」のものを取得 2)商品シリアル紐付へ、 入力した商品の情報をつけてシリアルをinsert 3)シリアルマスタのステータスを「使用済み」にupdate → 1回のupdate で35秒かかっていた → 100万件の場合、35秒×100回!
  31. 31. updateではまった話④ □update が遅かった原因 → update 時にindex の再構築が発生 → シリアルがランダムなため、 紐付く主キーの読込みが重い。。 read_buffer_size (16k)ずつ 読み込まれる 紐付く主キーがバラバラなた め、読込が毎回発生
  32. 32. updateではまった話⑤ □対応 ステータス管理をやめ、 管理テーブルを作成し、 update 自体を不要にした → 60分が45秒に改善! → インデックスの再構築怖い。。。
  33. 33. そんなこんなで、 なんとか無事リリースできました よかった
  34. 34. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・その他 Perlのチューニング ・まとめ
  35. 35. 今後の課題① □増分バックアップ 現状mysqldump でフルバックアップ → 今後さらにデータが増えてくると、 バイナリログを使った 増分バックアップの方がよさそう
  36. 36. 今後の課題② □データ退避とかパーティショニング → 古いシリアルの退避とか、 できれば「xxxx_2015」とか作りたくないので、 うまくパーティションとか使えると。。
  37. 37. Topic ・システムの概要 ・負荷テストした話 ・2億件登録したときの話 ・updateではまった話 ・今後の課題 ・その他 Perlのチューニング ・まとめ
  38. 38. その他 Perlのチューニング① □コネクションプーリングっぽいこと コネクションオブジェクトを シングルトンにし、1worker 1コネクションを共有 → コネクション生成のコストをなくした
  39. 39. その他 Perlのチューニング② □マスタデータをキャッシュ PSGIサーバ起動時に、メモリにDBのマスタデータを保持 → worker 内でメモリは共有されるため、 DBアクセスが不要になる ※ただし、「Copy-On-Write」なので、 書き換えようとすると、メモリリークの原因になる ※ただし、マスタデータを変更する場合には、 再起動が必要になるので、 本当はmemcached とかを使った方がよさそう
  40. 40. まとめ① □innodb_buffer_pool_size は大きい方がいい □主キーはシーケンスにした方がinsert が早い □インデックスの再構築は意外とばかにならない
  41. 41. まとめ② □負荷テスト大事 実際のデータに近いデータでやる □結局計測してみないとわからないことは多い → 効果測定にすごく時間がかかるので、 負荷テストとかは、早めにやる
  42. 42. ありがとうございました!

×