Skip to content
This repository has been archived by the owner on Jun 29, 2020. It is now read-only.

Acitivity 激重に対する SQL レベルでの修正 #945

Merged
merged 3 commits into from Aug 28, 2015

Conversation

lambdalisue
Copy link
Member

#867 #944

この修正しても遅いとは思うけど、とりあえず SQL 側での対応をしてみた。
この変更でどれくらい早くなる(or 変わらない・遅くなる)のか調査してほしい @miio

django_activity のスロークエリが二回飛んでいた問題を修正
{% if activities|length > 10 %} の部分が下記のような流れになるらしい

1. SELECT * FROM ... の SQL を投げ Python のリスト化
2. Python のリストに対して len() を呼ぶ

そのため上記部分を {% if activities.count > 10 %} にすることで SELECT * ではなく
SELECT COUNT(*) が呼ばれるように修正した
django_activity の場合サブクエリにて content_object 毎に最新の activity を取得するという処理を行っている。
したがってサブクエリに対しての LIMIT/OFFSET 適用が可能であり、そちらのほうがリクエストするオブジェクト数が少なくなる気がする(未確認)

変更前
SELECT ... FROM activities_activity WHERE id IN (
    SELECT MAX(id) AS pk FROM activities_activity GROUP BY ... ORDER BY NULL DESC
) ORDER BY created_at DESC LIMIT 10 OFFSET 10

変更後
SELECT ... FROM activities_activity WHERE id IN (
    SELECT MAX(id) AS pk FROM activities_activity GROUP BY ... ORDER BY created_at DESC LIMIT 10 OFFSET 10
) ORDER BY created_at DESC
@@ -49,7 +49,7 @@ <h4 class="modal-title">ようこそ、Kawazへ!</h4>
</div>
{% get_latest_activities as activities %}
{% include "activities/components/activity_container.html" with activities=activities|slice:":10" %}
{% if activities|length > 10 %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これって内部的にcount呼んでくれませんでしたっけ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

俺もそう思ってた。
本番鯖でSQL見た所問題のクエリが2回投げられてて、なんでかなーって見てたところ、ここで呼んでた。詳細はコミットログ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

勉強になる 📝

'SELECT *, MAX(id) AS id FROM activities_activity GROUP BY '
'content_type_id, object_id ORDER BY id DESC'
)
qs.count = lambda: len(list(qs))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

うっ、厳しそう

ORM使えるなら使いたいけど仕方なさそうですな

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/django/django/blob/master/django/db/models/sql/query.py#L157 のコメント的には下記コードで動くべきだと思うんだが

qs = super().get_queryset()
qs.query.group_by = ['content_type_id', 'object_id']
qs = qs.annotate(max_id=Max('id'))
qs = qs.order_by('max_id')

これで出てきて欲しいのは上記で書いたような SQL なんだけど、実際は

SELECT *, MAX(id) AS max_id FROM activities_activity GROUP BY content_type_id, object_id, id, _snapshot, ... ORDER BY id DESC

と参照してるフィールド全部羅列される。これは https://github.com/django/django/blob/master/django/db/models/sql/query.py#L1677 のせいっぽい。

もうすこし詳しく調べてみるけど、とりあえずこのブランチで速度上がるかテストして欲しいって感じ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

djangoにcontributeチャンス!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

group_byは複雑かつ罠が多いからdjangoが公式にサポートすることは無いと思うよ

@giginet
Copy link
Member

giginet commented Aug 28, 2015

通しますわよ

giginet added a commit that referenced this pull request Aug 28, 2015
…vity

Acitivity 激重に対する SQL レベルでの修正
@giginet giginet merged commit aade0e5 into develop Aug 28, 2015
@giginet giginet deleted the fix/slow_query_in_django_activity branch August 28, 2015 15:26
giginet added a commit that referenced this pull request Aug 31, 2015
…ngo_activity"

This reverts commit aade0e5, reversing
changes made to 70c0a82.
giginet added a commit that referenced this pull request Sep 1, 2015
Revert "Merge pull request #945 from kawazrepos/fix/slow_query_in_dja…
@giginet giginet mentioned this pull request Sep 11, 2015
5 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants