Pycon2014 django performance

59
Djangoアプリケーション パフォーマンスチューニング @hirokiky

description

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

Transcript of Pycon2014 django performance

Page 1: Pycon2014 django performance

Djangoアプリケーションパフォーマンスチューニング

@hirokiky

Page 2: Pycon2014 django performance

話すこと

Djangoアプリケーション高速化

パフォーマンス測定ツール

Page 3: Pycon2014 django performance

話さないこと

ミドルウェアパラメータ調整

検証用データの作成方法

なんか魔法みたいに速くなる技

Page 4: Pycon2014 django performance

自己紹介

@hirokiky

Python Django 好き

ギョームで100万ユーザーくらいのサイト

Django本体への貢献

Page 5: Pycon2014 django performance

Github

https://github.com/hirokiky/

Page 6: Pycon2014 django performance

Djangoアプリ高速化

SQLを吐きまくるコードは誰だ

インデックス

キャッシュキャッシュキャッシュ

アプリケーション外

Page 7: Pycon2014 django performance

SQLを吐きまくるコードは誰だ

● django-debug-toolbar

dbログ出力

Page 8: Pycon2014 django performance

django-debug-toolbar

デモ

https://pypi.python.org/pypi/django-debug-toolbar

Page 9: Pycon2014 django performance

django-debug-toolbar

Page 10: Pycon2014 django performance

dbログ出力

Page 11: Pycon2014 django performance

dbログ出力設定例

LOGGING['loggers']['django.db.backends'] = {

'level': 'DEBUG',

'handlers': ['console']

}

'console'ハンドラーは標準出力に表示する想定

Page 12: Pycon2014 django performance

SQLを吐きまくるコードを倒す

● .select_related/.prefetch_related

.bulk_create / .update

.count / .exists

Page 13: Pycon2014 django performance

.select_related (demo)

● FK先のデータも一緒に取ってくる

内部的にはJOINなどが走る

Page 14: Pycon2014 django performance

.prefetch_related (demo)

● FK元のデータも一緒に取ってくる

複数クエリを実行しPython側で結合

Page 15: Pycon2014 django performance

.bulk_create (demo)

● 複数のオブジェクトを一度に作成

Page 16: Pycon2014 django performance

.update

Page 17: Pycon2014 django performance

.exist - countダメ

Page 18: Pycon2014 django performance

その他

● .only / .defer

.values / .values_list

アプリケーションが複雑化しやすい....

Page 19: Pycon2014 django performance

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)

ここでクエリ実行

Page 20: Pycon2014 django performance

ここまでのまとめ

● ORMが実行するSQLを知ろう

ORMの特性を意識しよう

他にも: https://docs.djangoproject.com/en/1.7/topics/db/optimization/

Page 21: Pycon2014 django performance

インデックス

● 適切なインデックスを使おう

結局相手にしてるのはRDB

Page 22: Pycon2014 django performance

インデックス

1) 吐かれてるSQLをみて適応してく

2) インデックスがかかるクエリに変更

Page 23: Pycon2014 django performance

吐かれるクエリは?

JetProfilerなどがツールも優秀です

検証環境などにデータたっぷりいれて

画面をポチポチします

Page 24: Pycon2014 django performance

JetProfiler for MySQL

http://www.jetprofiler.com/tour/

Page 25: Pycon2014 django performance

インデックスの貼り方

ここでは話しません

Page 26: Pycon2014 django performance

インデックスがかかるクエリにする

.extra: クエリの一部分を生SQLで書く

.raw: クエリを生SQLで書く

複雑化しやすいのでキャッシュとの兼ね合いです

Page 27: Pycon2014 django performance

ここまでのまとめ

あとそもそもテーブルの設計ちゃんとしましょう

● クエリを眺めてインデックス適応

好みのクエリを走るようにする

Page 28: Pycon2014 django performance

キャッシュキャッシュキャッシュ

キャッシュの種類と使いどころ

Redisでのキャッシュ

Page 29: Pycon2014 django performance

キャッシュの種類

レスポンスキャッシュ

ビューキャッシュ

テンプレートキャッシュ

オブジェクトキャッシュ

効果的

https://docs.djangoproject.com/en/1.7/topics/cache/

Page 30: Pycon2014 django performance

テンプレートキャッシュ

{% load cache %}

{% cache 500 sidebar %}

.. sidebar ..

{% endcache %}

https://docs.djangoproject.com/en/1.7/topics/cache/

Page 31: Pycon2014 django performance

キャッシュの使いどころ

ユーザーに依存する表示は基本キャッシュ無理

画面設計段階でどこキャッシュできるか考える

Page 32: Pycon2014 django performance

Redisでキャッシュ

Redisならではの型を有効利用:

* Set型でユニークユーザーの管理

* SortedSet型でランキング

http://redis.io/

Page 33: Pycon2014 django performance

まとめ

ユーザーに近いほどキャッシュは有効

あまり複雑化しないように設計

Page 34: Pycon2014 django performance

アプリケーション外

セッションバックエンド変更

静的ファイル圧縮

DBのPrimary/Replica構成

Page 35: Pycon2014 django performance

セッションバックエンド変更

Cacheバックエンド

Redisのバックエンド

Page 36: Pycon2014 django performance

Redisバックエンド

SESSION_ENGINE = 'redis_sessions.session'

https://pypi.python.org/pypi/django-redis-sessions

$ pip install django-redis-sessions

Page 37: Pycon2014 django performance

静的ファイル圧縮

django-compressor か django-asset

Page 38: Pycon2014 django performance

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/

Page 39: Pycon2014 django performance

DBのMaster/Slave

django-replicatedが便利

レプリ遅延にも賢く対応

Page 40: Pycon2014 django performance

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 になります

Page 41: Pycon2014 django performance

レプリ遅延対策

MIDDLEWARE_CLASSES = [

...

'django_replicated.middleware.ReplicationMiddleware',

]

https://github.com/yandex/django_replicated

GET, HEADで slave, それ以外で master

Page 42: Pycon2014 django performance

レプリ遅延対策 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に強制指定

Page 43: Pycon2014 django performance

まとめ

ORMの使い方は基本としてマスター

インデックス+キャッシュのバランス

まんべんなくやっとくのが吉です

Page 44: Pycon2014 django performance

Funkloadでパフォーマンス測定

負荷試験ツール (Pythonで書く)

セッション付きのシナリオ

静的ファイルの自動取得などリッチ

https://funkload.nuxeo.org/

Page 45: Pycon2014 django performance

Funkload (テストシナリオ)

1) 一覧画面

2) 詳細画面

3) 編集画面

4) 更新

5) 詳細画面

Page 46: Pycon2014 django performance

Funkload (demo)

$ fl-run-test test_Wiki.py

$ fl-run-bench test_Wiki TestWiki.test_update

Page 47: Pycon2014 django performance

Funkload 一覧画面

Page 48: Pycon2014 django performance

Funkload 詳細画面

Page 49: Pycon2014 django performance

Funkload 編集画面

Page 50: Pycon2014 django performance

Funkload 更新

Page 51: Pycon2014 django performance

Funkload 詳細画面

Page 52: Pycon2014 django performance

Funkload レポートビルド

$ fl-run-test test_Wiki.py

$ fl-run-bench test_Wiki TestWiki.test_update

Page 53: Pycon2014 django performance

レポートその他

2レポート間の差分レポート

複数レポートでのトレンドレポート

Page 54: Pycon2014 django performance

耐えるべき負荷は?

アクティブユーザー10万人、1日100万PV

ピーク時でその3倍として秒間34PV

人間1人5秒/1ページとして同時接続数170

このあたり模索中で良い方法などあれば教えてください

Page 55: Pycon2014 django performance

ここまでのまとめ

FunkloadはPythonで書ける

シナリオでかけるので信頼できる

Page 56: Pycon2014 django performance

全体まとめ

ORMの扱いなどは当たり前にやっておく

面倒、複雑なものは測定しつつ必要な分やる

Page 57: Pycon2014 django performance

感想

カッコいいこと言っても結局

設計とミドルウェアが重要

どううまく使うかを考えましょう

Page 58: Pycon2014 django performance

出会い系

オフィスアワー(会議室4/5)に13:15〜

Sprint(3日目)

Page 59: Pycon2014 django performance

@hirokiky