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