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.

Pycon2014 django performance

10,022 views

Published on

Djangoアプリケーションチューニング、Djangoアプリケーションのチューニング方法、負荷測定方法を紹介します。PyConJP2014での発表資料です。
発表の動画はこちら http://youtu.be/1aLAZG4Udg0

Published in: Internet

Pycon2014 django performance

  1. 1. Djangoアプリケーション パフォーマンスチューニング @hirokiky
  2. 2. 話すこと Djangoアプリケーション高速化 パフォーマンス測定ツール
  3. 3. 話さないこと ミドルウェアパラメータ調整 検証用データの作成方法 なんか魔法みたいに速くなる技
  4. 4. 自己紹介 @hirokiky Python Django 好き ギョームで100万ユーザーくらいのサイト Django本体への貢献
  5. 5. Github https://github.com/hirokiky/
  6. 6. Djangoアプリ高速化 SQLを吐きまくるコードは誰だ インデックス キャッシュキャッシュキャッシュ アプリケーション外
  7. 7. SQLを吐きまくるコードは誰だ ● django-debug-toolbar dbログ出力
  8. 8. django-debug-toolbar デモ https://pypi.python.org/pypi/django-debug-toolbar
  9. 9. django-debug-toolbar
  10. 10. dbログ出力
  11. 11. dbログ出力設定例 LOGGING['loggers']['django.db.backends'] = { 'level': 'DEBUG', 'handlers': ['console'] } 'console'ハンドラーは標準出力に表示する想定
  12. 12. SQLを吐きまくるコードを倒す ● .select_related/.prefetch_related .bulk_create / .update .count / .exists
  13. 13. .select_related (demo) ● FK先のデータも一緒に取ってくる 内部的にはJOINなどが走る
  14. 14. .prefetch_related (demo) ● FK元のデータも一緒に取ってくる 複数クエリを実行しPython側で結合
  15. 15. .bulk_create (demo) ● 複数のオブジェクトを一度に作成
  16. 16. .update
  17. 17. .exist - countダメ
  18. 18. その他 ● .only / .defer .values / .values_list アプリケーションが複雑化しやすい....
  19. 19. QuerySetはlazy >>> articles = Article.objects.all() >>> articles = articles.filter(title__startswith='title') >>> print(articles) >>> >>> q = articles.filter(author_id=1) >>> print(q) ここでクエリ実行 https://docs.djangoproject.com/en/1.7/topics/db/queries/#querysets-are-lazy
  20. 20. ここまでのまとめ ● ORMが実行するSQLを知ろう ORMの特性を意識しよう 他にも: https://docs.djangoproject.com/en/1.7/topics/db/optimization/
  21. 21. インデックス ● 適切なインデックスを使おう 結局相手にしてるのはRDB
  22. 22. インデックス 1) 吐かれてるSQLをみて適応してく 2) インデックスがかかるクエリに変更
  23. 23. 吐かれるクエリは? 検証環境などにデータたっぷりいれて 画面をポチポチします JetProfilerなどがツールも優秀です
  24. 24. JetProfiler for MySQL http://www.jetprofiler.com/tour/
  25. 25. インデックスの貼り方 ここでは話しません
  26. 26. インデックスがかかるクエリにする .extra: クエリの一部分を生SQLで書く .raw: クエリを生SQLで書く 複雑化しやすいのでキャッシュとの兼ね合いです
  27. 27. ここまでのまとめ ● クエリを眺めてインデックス適応 好みのクエリを走るようにする あとそもそもテーブルの設計ちゃんとしましょう
  28. 28. キャッシュキャッシュキャッシュ キャッシュの種類と使いどころ Redisでのキャッシュ
  29. 29. キャッシュの種類 レスポンスキャッシュ ビューキャッシュ テンプレートキャッシュ オブジェクトキャッシュ 効果的 https://docs.djangoproject.com/en/1.7/topics/cache/
  30. 30. テンプレートキャッシュ {% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %} https://docs.djangoproject.com/en/1.7/topics/cache/
  31. 31. キャッシュの使いどころ ユーザーに依存する表示は基本キャッシュ無理 画面設計段階でどこキャッシュできるか考える
  32. 32. Redisでキャッシュ Redisならではの型を有効利用: * Set型でユニークユーザーの管理 * SortedSet型でランキング http://redis.io/
  33. 33. まとめ ユーザーに近いほどキャッシュは有効 あまり複雑化しないように設計
  34. 34. アプリケーション外 セッションバックエンド変更 静的ファイル圧縮 DBのPrimary/Replica構成
  35. 35. セッションバックエンド変更 Cacheバックエンド Redisのバックエンド
  36. 36. Redisバックエンド $ pip install django-redis-sessions SESSION_ENGINE = 'redis_sessions.session' https://pypi.python.org/pypi/django-redis-sessions
  37. 37. 静的ファイル圧縮 django-compressor か django-asset
  38. 38. django-compressor {% load compress %} {% compress css %} <link rel="stylesheet" href="/static/css/one.css" type="text/css"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css"> {% endcompress %} http://django-compressor.readthedocs.org/en/latest/
  39. 39. DBのMaster/Slave django-replicatedが便利 レプリ遅延にも賢く対応
  40. 40. django-replicated $ pip install django-replicated DATABASES = {'default': {...}, 'slave1': {...}} DATABASE_SLAVES = ['slave1'] DATABASE_ROUTERS = ['django_replicated.ReplicationRouter'] 更新が master, 参照が slave になります https://github.com/yandex/django_replicated
  41. 41. レプリ遅延対策 MIDDLEWARE_CLASSES = [ ... 'django_replicated.middleware.ReplicationMiddleware', ] GET, HEADで slave, それ以外で master https://github.com/yandex/django_replicated
  42. 42. レプリ遅延対策 2 from django_replicated.decorators import use_master, use_slave @use_master def my_view(request, ...): # GETで更新&参照するViewなんだぜ。。。 Viewに強制指定 https://github.com/yandex/django_replicated
  43. 43. まとめ ORMの使い方は基本としてマスター インデックス+キャッシュのバランス まんべんなくやっとくのが吉です
  44. 44. Funkloadでパフォーマンス測定 負荷試験ツール (Pythonで書く) セッション付きのシナリオ 静的ファイルの自動取得などリッチ https://funkload.nuxeo.org/
  45. 45. Funkload (テストシナリオ) 1) 一覧画面 2) 詳細画面 3) 編集画面 4) 更新 5) 詳細画面
  46. 46. Funkload (demo) $ fl-run-test test_Wiki.py $ fl-run-bench test_Wiki TestWiki.test_update
  47. 47. Funkload 一覧画面
  48. 48. Funkload 詳細画面
  49. 49. Funkload 編集画面
  50. 50. Funkload 更新
  51. 51. Funkload 詳細画面
  52. 52. Funkload レポートビルド $ fl-run-test test_Wiki.py $ fl-run-bench test_Wiki TestWiki.test_update
  53. 53. レポートその他 2レポート間の差分レポート 複数レポートでのトレンドレポート
  54. 54. 耐えるべき負荷は? アクティブユーザー10万人、1日100万PV ピーク時でその3倍として秒間34PV 人間1人5秒/1ページとして同時接続数170 このあたり模索中で良い方法などあれば教えてください
  55. 55. ここまでのまとめ FunkloadはPythonで書ける シナリオでかけるので信頼できる
  56. 56. 全体まとめ ORMの扱いなどは当たり前にやっておく 面倒、複雑なものは測定しつつ必要な分やる
  57. 57. 感想 カッコいいこと言っても結局 設計とミドルウェアが重要 どううまく使うかを考えましょう
  58. 58. 出会い系 オフィスアワー(会議室4/5)に13:15〜 Sprint(3日目)
  59. 59. @hirokiky

×