ducdev
Python / Bài viết

Django ORM — Những Query Tối Ưu Mà Ít Developer Biết

Django ORM rất tiện nhưng cũng dễ viết code kém hiệu năng mà không hay biết. Khám phá các kỹ thuật query tối ưu từ select_related đến annotate và aggregate.

a
admin
27/01/2026 · 3 phút đọc · 0 lượt xem
Chia sẻ

Django ORM là một trong những lý do nhiều developer yêu thích Django. Nhưng sự tiện lợi đó đôi khi che giấu những query kém hiệu năng đang chạy ngầm. Hãy cùng khám phá những kỹ thuật ít được biết đến.

Hiểu Lazy Evaluation

QuerySet trong Django là lazy — chúng không hit database cho đến khi bạn thực sự cần data:

# Chưa query database
posts = Post.objects.filter(status='published')
posts = posts.order_by('-published_at')
posts = posts[:10]

# Query xảy ra ở đây — khi evaluate
for post in posts:
    print(post.title)

Điều này có nghĩa là bạn có thể chain filters và conditions mà không lo về performance.

select_related Và prefetch_related

# select_related — cho ForeignKey và OneToOne (1 JOIN query)
posts = Post.objects.select_related('author', 'category')

# prefetch_related — cho ManyToMany và reverse FK (2 queries)
posts = Post.objects.prefetch_related('tags', 'comments')

# Kết hợp cả hai
posts = Post.objects.select_related('author').prefetch_related('tags')

only() Và defer() — Chỉ Lấy Cột Cần

# only() — chỉ lấy các field được chỉ định
posts = Post.objects.only('id', 'title', 'slug', 'published_at')

# defer() — lấy tất cả TRỪ các field chỉ định
# Hữu ích khi content là TextField lớn không cần thiết
posts = Post.objects.defer('content', 'meta_description')

values() Và values_list() — Bỏ Qua Model Instances

# values() — trả về list of dicts
posts = Post.objects.values('id', 'title', 'author__username')
# [{'id': 1, 'title': 'Hello', 'author__username': 'duc'}]

# values_list() — trả về list of tuples
titles = Post.objects.values_list('title', flat=True)
# ['Hello', 'World', ...]

# Hữu ích cho APIs trả JSON hoặc lấy danh sách IDs
post_ids = Post.objects.filter(status='published').values_list('id', flat=True)

annotate() — Tính Toán Tại Database

from django.db.models import Count, Avg

# Đếm số comment cho mỗi bài viết
posts = Post.objects.annotate(
    comment_count=Count('comments')
).order_by('-comment_count')

# Dùng annotation trong template
# {{ post.comment_count }}

aggregate() — Tổng Hợp Toàn Bộ QuerySet

from django.db.models import Count, Sum, Avg, Max

stats = Post.objects.aggregate(
    total=Count('id'),
    total_views=Sum('views'),
    avg_reading_time=Avg('reading_time'),
    max_views=Max('views')
)
# {'total': 50, 'total_views': 12500, ...}

F() Expressions — Tham Chiếu Field Trong Query

from django.db.models import F

# Tăng view count mà không cần đọc trước
Post.objects.filter(id=1).update(views=F('views') + 1)

# So sánh hai fields
Post.objects.filter(views__gt=F('reading_time') * 100)

Q() Objects — Query Phức Tạp

from django.db.models import Q

# OR condition
posts = Post.objects.filter(
    Q(status='published') | Q(author__is_staff=True)
)

# AND với NOT
posts = Post.objects.filter(
    Q(status='published') & ~Q(category__name='Draft')
)
Mỗi khi bạn thấy mình đang loop qua QuerySet và gọi thêm query bên trong — đó là dấu hiệu cần dùng annotate, select_related, hoặc prefetch_related.

Kết Luận

Django ORM đủ mạnh để xử lý hầu hết các trường hợp mà không cần raw SQL. Chìa khóa là hiểu khi nào QuerySet hit database và tận dụng tối đa các công cụ như annotate, F(), Q() để đẩy computation xuống database thay vì xử lý trong Python.

#Django #ORM #Python #database #Performance
a
Tác giả
admin

Lập trình viên, yêu thích chia sẻ kiến thức về công nghệ và phát triển phần mềm.

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!

Để lại bình luận

Bình luận sẽ được duyệt trước khi hiển thị.