Π‘Π½ΠΈΠΆΠ΅Π½ΠΈΠ΅ p95 latency Π² Django: N+1, ΠΊΠ΅ΡΠΈ ΠΈ Π²ΡΠ½ΠΎΡ Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ
Π§ΡΠΎ Π»ΠΎΠΌΠ°Π΅ΡΡΡ Π² ΠΏΡΠΎΠ΄Π΅
ΠΡΠ΅Π΄ΡΡΠ°Π²ΡΡΠ΅ ΡΠ΅Π±Π΅: ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ ΠΆΠ°Π»ΡΡΡΡΡ Π½Π° ΠΌΠ΅Π΄Π»Π΅Π½Π½ΡΡ ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π° ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ, ΡΡΠΎ 95% Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΠΎΠΉ Π±ΠΎΠ»Π΅Π΅ 2 ΡΠ΅ΠΊΡΠ½Π΄. ΠΡΠΈ ΡΡΠΎΠΌ ΡΠ΅ΡΠ²Π΅ΡΡ Π½Π΅ ΠΏΠ΅ΡΠ΅Π³ΡΡΠΆΠ΅Π½Ρ, Π° Π±Π°Π·Π° Π΄Π°Π½Π½ΡΡ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΠΎ. Π ΡΠ΅ΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°?
Π§Π°ΡΡΠΎ ΠΏΡΠΈΡΠΈΠ½ΠΎΠΉ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠ° N+1, ΠΊΠΎΠ³Π΄Π° Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΡΠ»ΠΈΡΠΊΠΎΠΌ ΠΌΠ½ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΊ Π±Π°Π·Π΅. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΈ Π·Π°Π³ΡΡΠ·ΠΊΠ΅ ΡΠΏΠΈΡΠΊΠ° Π·Π°ΠΊΠ°Π·ΠΎΠ² Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π·Π°ΠΊΠ°Π·Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°ΡΡΡΡ ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°Ρ ΠΈΠ»ΠΈ ΡΠΎΠ²Π°ΡΠ°Ρ . ΠΡΠΎ ΠΏΡΠΈΠ²ΠΎΠ΄ΠΈΡ ΠΊ Π»Π°Π²ΠΈΠ½ΠΎΠΎΠ±ΡΠ°Π·Π½ΠΎΠΌΡ ΡΠΎΡΡΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° SQL-Π·Π°ΠΏΡΠΎΡΠΎΠ².
ΠΡΡΠ³ΠΎΠΉ ΡΠ°ΡΡΡΠΉ ΡΡΠ΅Π½Π°ΡΠΈΠΉ β ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ. ΠΠ°ΠΆΠ΅ Π΅ΡΠ»ΠΈ Π΄Π°Π½Π½ΡΠ΅ ΡΠ΅Π΄ΠΊΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ, ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π· ΠΎΠ±ΡΠ°ΡΠ°Π΅ΡΡΡ ΠΊ Π±Π°Π·Π΅, ΡΡΠΎ ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°Π΅Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΠΈ. ΠΠ°ΠΊΠΎΠ½Π΅Ρ, ΡΡΠΆΠ΅Π»ΡΠ΅ ΡΠΎΠ½ΠΎΠ²ΡΠ΅ Π·Π°Π΄Π°ΡΠΈ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΡ ΠΎΡΡΠ΅ΡΠΎΠ² ΠΈΠ»ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π±ΠΎΠ»ΡΡΠΈΡ ΠΎΠ±ΡΠ΅ΠΌΠΎΠ² Π΄Π°Π½Π½ΡΡ , ΠΌΠΎΠ³ΡΡ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²Π°ΡΡ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΡΠ΅ΡΡΡΡΡ, Π·Π°ΠΌΠ΅Π΄Π»ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ².
Π§ΡΠΎ ΠΌΠ΅Π½ΡΡΡ ΡΠ΅Ρ Π½ΠΈΡΠ΅ΡΠΊΠΈ
Π§ΡΠΎΠ±Ρ ΡΠ½ΠΈΠ·ΠΈΡΡ p95 latency, Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΡΡΡΠ°Π½ΠΈΡΡ ΠΊΠΎΡΠ½Π΅Π²ΡΠ΅ ΠΏΡΠΈΡΠΈΠ½Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ. ΠΠΎΡ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌΡΠΉ ΡΠ΅ΠΊΠ»ΠΈΡΡ:
1. ΠΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΈ ΡΡΡΡΠ°Π½Π΅Π½ΠΈΠ΅ N+1 Π·Π°ΠΏΡΠΎΡΠΎΠ²
ΠΡΠΈΠ±ΠΊΠ° N+1 Π·Π°ΠΏΡΠΎΡΠΎΠ² Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ, ΠΊΠΎΠ³Π΄Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½ΡΡ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π² ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π² Django ΡΡΠΎ ΡΠ°ΡΡΠΎ ΡΠ»ΡΡΠ°Π΅ΡΡΡ ΠΏΡΠΈ Π΄ΠΎΡΡΡΠΏΠ΅ ΠΊ ΡΠ²ΡΠ·Π°Π½Π½ΡΠΌ ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌ Π² ΡΠΈΠΊΠ»Π΅. Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΡΠΈΠΌΠ΅Ρ:
# ΠΡΠΈΠΌΠ΅Ρ N+1 ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ
orders = Order.objects.all()
for order in orders:
print(order.customer.name) # ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π· Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ SQL-Π·Π°ΠΏΡΠΎΡ Π΄Π»Ρ customer
Π ΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π·Π°ΠΊΠ°Π·Π° Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ ΠΎ ΠΊΠ»ΠΈΠ΅Π½ΡΠ΅. ΠΡΠ»ΠΈ Ρ Π½Π°Ρ 100 Π·Π°ΠΊΠ°Π·ΠΎΠ², ΡΡΠΎ ΠΏΡΠΈΠ²Π΅Π΄Π΅Ρ ΠΊ 101 Π·Π°ΠΏΡΠΎΡΡ (1 Π·Π°ΠΏΡΠΎΡ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΡΠ΅Ρ Π·Π°ΠΊΠ°Π·ΠΎΠ² ΠΈ 100 Π·Π°ΠΏΡΠΎΡΠΎΠ² Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ ΠΎ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°Ρ ).
ΠΠ°ΠΊ ΠΈΡΠΏΡΠ°Π²ΠΈΡΡ
ΠΠ»Ρ ΡΡΡΡΠ°Π½Π΅Π½ΠΈΡ ΡΡΠΎΠΉ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π² Django ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ select_related ΠΈ prefetch_related:
# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ select_related Π΄Π»Ρ "ΠΆΠ°Π΄Π½ΠΎΠΉ" Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΡΠ²ΡΠ·Π°Π½Π½ΡΡ
Π΄Π°Π½Π½ΡΡ
orders = Order.objects.select_related('customer').all()
for order in orders:
print(order.customer.name) # Π΄Π°Π½Π½ΡΠ΅ ΠΎ customer ΡΠΆΠ΅ Π·Π°Π³ΡΡΠΆΠ΅Π½Ρ
select_related ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΠΈΡ Π΄Π»Ρ "ΠΎΠ΄ΠΈΠ½-ΠΊ-ΠΎΠ΄Π½ΠΎΠΌΡ" ΠΈΠ»ΠΈ "ΠΌΠ½ΠΎΠ³ΠΈΠ΅-ΠΊ-ΠΎΠ΄Π½ΠΎΠΌΡ" ΡΠ²ΡΠ·Π΅ΠΉ. ΠΠ»Ρ "ΠΌΠ½ΠΎΠ³ΠΈΠ΅-ΠΊΠΎ-ΠΌΠ½ΠΎΠ³ΠΈΠΌ" ΠΈΠ»ΠΈ "ΠΎΠ΄ΠΈΠ½-ΠΊΠΎ-ΠΌΠ½ΠΎΠ³ΠΈΠΌ" ΡΠ²ΡΠ·Π΅ΠΉ Π»ΡΡΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ prefetch_related, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ, Π½ΠΎ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΠ΅Ρ Π΅Π³ΠΎ:
# ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ prefetch_related Π΄Π»Ρ "Π»Π΅Π½ΠΈΠ²ΠΎΠΉ" Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΡΠ²ΡΠ·Π°Π½Π½ΡΡ
Π΄Π°Π½Π½ΡΡ
orders = Order.objects.prefetch_related('items').all()
for order in orders:
for item in order.items.all():
print(item.name)
ΠΠ°ΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ½ΠΈΡΡ, ΡΡΠΎ select_related ΠΈ prefetch_related Π½Π΅ Π²ΡΠ΅Π³Π΄Π° Π²Π·Π°ΠΈΠΌΠΎΠ·Π°ΠΌΠ΅Π½ΡΠ΅ΠΌΡ. ΠΡΠΈΠ±ΠΎΡΠ½ΡΠΉ Π²ΡΠ±ΠΎΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ²Π΅ΡΡΠΈ ΠΊ ΡΠ²Π΅Π»ΠΈΡΠ΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΌΠ° Π΄Π°Π½Π½ΡΡ , ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΡΡ ΠΈΠ· Π±Π°Π·Ρ, ΡΡΠΎ ΡΠΎΠΆΠ΅ Π½Π΅Π³Π°ΡΠΈΠ²Π½ΠΎ ΡΠΊΠ°ΠΆΠ΅ΡΡΡ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ.
ΠΠ°ΠΊ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅
django-debug-toolbar, ΡΡΠΎΠ±Ρ ΡΠ²ΠΈΠ΄Π΅ΡΡ, ΡΠΊΠΎΠ»ΡΠΊΠΎ Π·Π°ΠΏΡΠΎΡΠΎΠ² Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΡΡΠ°Π½ΠΈΡΡ. - ΠΡΠΈΠΌΠ΅Π½ΠΈΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄
.queryΠΊ QuerySet, ΡΡΠΎΠ±Ρ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ SQL. - ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ ΠΏΠ»Π°Π½ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² Ρ ΠΏΠΎΠΌΠΎΡΡΡ EXPLAIN Π² Π²Π°ΡΠ΅ΠΉ Π±Π°Π·Π΅ Π΄Π°Π½Π½ΡΡ , ΡΡΠΎΠ±Ρ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ.
2. ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ
ΠΡΠ»ΠΈ Π²Π°ΡΠΈ Π΄Π°Π½Π½ΡΠ΅ ΡΠ΅Π΄ΠΊΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ, Π½ΠΎ Π°ΠΊΡΠΈΠ²Π½ΠΎ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°ΡΡΡΡ, ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠ½ΠΈΠ·ΠΈΡΡ Π·Π°Π΄Π΅ΡΠΆΠΊΠΈ. Π Django Π΅ΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΠΎΠ²Π½Π΅ΠΉ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ:
ΠΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° ΡΡΠΎΠ²Π½Π΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠΉ
ΠΡΠΎ ΡΠ°ΠΌΡΠΉ ΠΏΡΠΎΡΡΠΎΠΉ ΡΠΏΠΎΡΠΎΠ± ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ. ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π΅ΠΊΠΎΡΠ°ΡΠΎΡ @cache_page, ΡΡΠΎΠ±Ρ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°ΡΡ Π²Π΅ΡΡ Π²ΡΠ²ΠΎΠ΄ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΡ:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # ΠΠ΅ΡΠΈΡΡΠ΅ΠΌ Π½Π° 15 ΠΌΠΈΠ½ΡΡ
def my_view(request):
# ...
ΠΠ΄Π½Π°ΠΊΠΎ ΡΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½Π΅ Π·Π°Π²ΠΈΡΡΡ ΠΎΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π»Ρ ΠΏΡΠ±Π»ΠΈΡΠ½ΡΡ ΡΡΡΠ°Π½ΠΈΡ.
ΠΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° ΡΡΠΎΠ²Π½Π΅ Π΄Π°Π½Π½ΡΡ
ΠΠ»Ρ Π±ΠΎΠ»Π΅Π΅ ΡΠΎΠ½ΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ django.core.cache Π΄Π»Ρ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ
ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΠΈΠ»ΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠΎΠ² Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠΉ:
from django.core.cache import cache
def get_expensive_data(param):
cache_key = f"expensive_data_{param}"
data = cache.get(cache_key)
if not data:
data = calculate_expensive_data(param)
cache.set(cache_key, data, 60 * 15) # ΠΠ΅ΡΠΈΡΡΠ΅ΠΌ Π½Π° 15 ΠΌΠΈΠ½ΡΡ
return data
ΠΡΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠΈ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π²Π°ΠΆΠ½ΠΎ ΡΡΠΈΡΡΠ²Π°ΡΡ ΡΡΡΠ°ΡΠ΅Π³ΠΈΡ ΠΈΠ½Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ ΠΊΠ΅ΡΠ°, ΡΡΠΎΠ±Ρ Π΄Π°Π½Π½ΡΠ΅ ΠΎΡΡΠ°Π²Π°Π»ΠΈΡΡ Π°ΠΊΡΡΠ°Π»ΡΠ½ΡΠΌΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡΠΈΡΠ°ΡΡ ΠΊΠ΅Ρ ΠΏΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΡΠ²ΡΠ·Π°Π½Π½ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠΎΡΠΎΡΠΊΠΈΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½Π° ΠΆΠΈΠ·Π½ΠΈ (TTL).
ΠΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π½Π° ΡΡΠΎΠ²Π½Π΅ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ PostgreSQL, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌΡ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ pg_stat_statements Π΄Π»Ρ Π°Π½Π°Π»ΠΈΠ·Π° ΡΠ°ΡΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΠΌΡΡ
Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΈ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ² ΠΈΠ»ΠΈ ΠΌΠ°ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΡ
ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½ΠΈΠΉ Π΄Π»Ρ ΡΡΠΊΠΎΡΠ΅Π½ΠΈΡ ΠΈΡ
Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ.
ΠΠ°ΠΊ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³Π° ΠΊΠ΅ΡΠ°, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ
django-debug-toolbar, ΡΡΠΎΠ±Ρ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎ ΠΊΠ΅Ρ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ. - ΠΡΠΎΠ²Π΅ΡΡΠΉΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΊΠ΅Ρ-Ρ ΠΈΡΠΎΠ² ΠΈ ΠΏΡΠΎΠΌΠ°Ρ ΠΎΠ² (cache hits/misses), ΡΡΠΎΠ±Ρ ΠΎΡΠ΅Π½ΠΈΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
- Π’Π΅ΡΡΠΈΡΡΠΉΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ Π½Π°Π³ΡΡΠ·ΠΊΠΎΠΉ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² Π²ΡΠΎΠ΄Π΅
locustΠΈΠ»ΠΈwrk, ΡΡΠΎΠ±Ρ ΡΠ²ΠΈΠ΄Π΅ΡΡ, ΠΊΠ°ΠΊ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π²Π»ΠΈΡΠ΅Ρ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ.
3. ΠΡΠ½ΠΎΡ ΡΡΠΆΠ΅Π»ΡΡ Π·Π°Π΄Π°Ρ Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ
ΠΡΠ»ΠΈ Π²Π°ΡΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ ΡΠ΅ΡΡΡΡΠΎΠ΅ΠΌΠΊΠΈΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠΉ, ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΠΈΡΠ΅ΠΌ ΠΈΠ»ΠΈ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΡ ΠΎΡΡΠ΅ΡΠΎΠ², ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π·Π°Π½ΠΈΠΌΠ°ΡΡ Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ ΠΈ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ Π΄ΡΡΠ³ΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ². Π Π΅ΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΎΡΠ΅ΡΠ΅Π΄Π΅ΠΉ Π·Π°Π΄Π°Ρ.
ΠΡΠΈΠΌΠ΅Ρ Ρ Celery
Π ΡΠΊΠΎΡΠΈΡΡΠ΅ΠΌΠ΅ Django ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΡΠΌ Π²ΡΠ±ΠΎΡΠΎΠΌ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΎΡΠ΅ΡΠ΅Π΄ΡΠΌΠΈ Π·Π°Π΄Π°Ρ ΡΠ²Π»ΡΠ΅ΡΡΡ Celery. ΠΠΎΡ ΠΏΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:
from celery import shared_task
@shared_task
def send_email_task(email_address, subject, message):
# ΠΠΎΠ³ΠΈΠΊΠ° ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ ΠΏΠΈΡΡΠΌΠ°
pass
# ΠΡΠ·ΠΎΠ² Π·Π°Π΄Π°ΡΠΈ
send_email_task.delay('user@example.com', 'Π’Π΅ΠΌΠ°', 'Π‘ΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅')
Π ΡΡΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π·Π°Π΄Π°ΡΠ° send_email_task Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½Π° Π² ΡΠΎΠ½ΠΎΠ²ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅, Π½Π΅ Π±Π»ΠΎΠΊΠΈΡΡΡ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΏΠΎΡΠΎΠΊ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ.
ΠΡΠ±ΠΎΡ Π±ΡΠΎΠΊΠ΅ΡΠ° Π·Π°Π΄Π°Ρ
Celery ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΡΠ΅ Π±ΡΠΎΠΊΠ΅ΡΡ Π·Π°Π΄Π°Ρ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Redis ΠΈΠ»ΠΈ RabbitMQ. ΠΠ»Ρ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²Π° ΠΏΡΠΎΠ΅ΠΊΡΠΎΠ² Redis ΡΠ²Π»ΡΠ΅ΡΡΡ Ρ ΠΎΡΠΎΡΠΈΠΌ Π²ΡΠ±ΠΎΡΠΎΠΌ Π±Π»Π°Π³ΠΎΠ΄Π°ΡΡ ΠΏΡΠΎΡΡΠΎΡΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΠΈ Π²ΡΡΠΎΠΊΠΎΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ.
ΠΠ°ΠΊ ΠΏΡΠΎΠ²Π΅ΡΠΈΡΡ
- Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ Π·Π°Π΄Π°ΡΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π² ΠΎΡΠ΅ΡΠ΅Π΄ΠΈ, Π° Π½Π΅ Π² ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΌ ΠΏΠΎΡΠΎΠΊΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ.
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³Π°, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ Flower, ΡΡΠΎΠ±Ρ ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°ΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΎΡΠ΅ΡΠ΅Π΄Π΅ΠΉ ΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ Π·Π°Π΄Π°Ρ.
- ΠΡΠΎΠ²Π΅ΡΡΠΉΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ Π·Π°Π΄Π΅ΡΠΆΠ΅ΠΊ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°Π΄Π°Ρ, ΡΡΠΎΠ±Ρ ΡΠ±Π΅Π΄ΠΈΡΡΡΡ, ΡΡΠΎ ΠΎΠ½ΠΈ Π½Π΅ ΡΡΠ°Π½ΠΎΠ²ΡΡΡΡ ΡΠ·ΠΊΠΈΠΌ ΠΌΠ΅ΡΡΠΎΠΌ.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
Π‘Π½ΠΈΠΆΠ΅Π½ΠΈΠ΅ p95 latency ΡΡΠ΅Π±ΡΠ΅Ρ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Π°: ΡΡΡΡΠ°Π½Π΅Π½ΠΈΡ N+1 Π·Π°ΠΏΡΠΎΡΠΎΠ², Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΊΠ΅ΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΈ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠ° ΡΡΠΆΠ΅Π»ΡΡ Π·Π°Π΄Π°Ρ Π² ΡΠΎΠ½ΠΎΠ²ΡΠ΅ ΠΏΡΠΎΡΠ΅ΡΡΡ. ΠΡΠΈ ΡΠ°Π³ΠΈ ΠΏΠΎΠΌΠΎΠ³ΡΡ ΡΠ»ΡΡΡΠΈΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ Π²Π°ΡΠ΅Π³ΠΎ Django-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠΈΡΡ Π±ΠΎΠ»Π΅Π΅ Π±ΡΡΡΡΡΠΉ ΠΎΡΠΊΠ»ΠΈΠΊ Π΄Π»Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ.
ΠΡΠ»ΠΈ Π²Π°ΠΌ Π½ΡΠΆΠ½Π° ΠΏΠΎΠΌΠΎΡΡ Π² ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π²Π°ΡΠ΅Π³ΠΎ Django-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π·Π°ΠΏΠΈΡΠΈΡΠ΅ΡΡ Π½Π° ΠΊΠΎΠ½ΡΡΠ»ΡΡΠ°ΡΠΈΡ, ΠΈ Ρ ΠΏΠΎΠΌΠΎΠ³Ρ Π²Π°ΠΌ Π½Π°ΠΉΡΠΈ ΠΈ ΡΡΡΡΠ°Π½ΠΈΡΡ ΡΠ·ΠΊΠΈΠ΅ ΠΌΠ΅ΡΡΠ°.




