len()
, count()
, v.v. Hãy đảm bảo rằng bạn sử dụng chúng tốt nhất.
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, ) charged_amount = models.PositiveIntegerField()
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField()
# models.py from django.db import models class Sale(models.Model): sold_at = models.DateTimeField( auto_now_add=True, db_index=True, #DB Indexing ) charged_amount = models.PositiveIntegerField() class Meta: indexes = [ ["sold_at", "charged_amount"]]
ip:port
trong đó ip
là địa chỉ IP của daemon Memcached và port
là cổng mà Memcached đang chạy hoặc URL trỏ đến phiên bản Redis của bạn, sử dụng lược đồ thích hợp.
Để bật bộ nhớ đệm cơ sở dữ liệu với Memcached, hãy cài đặt pymemcache
bằng pip bằng lệnh sau:
pip install pymemcache
Sau đó, bạn có thể định cấu hình cài đặt bộ nhớ cache trong settings.py
của mình như sau:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache', 'LOCATION': '127.0.0.1:11211', } }
Trong ví dụ trên, Memcached đang chạy trên localhost (127.0.0.1) cổng 11211, sử dụng liên kết pymemcache
:
pip install redis
Sau đó, định cấu hình cài đặt bộ nhớ cache trong settings.py
của bạn bằng cách thêm mã sau:
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379', } }
Thông thường, một bộ truy vấn trong Django sẽ lưu vào bộ nhớ cache kết quả của nó khi quá trình đánh giá xảy ra và đối với bất kỳ hoạt động nào tiếp theo với bộ truy vấn đó, trước tiên nó sẽ kiểm tra xem có kết quả được lưu trong bộ nhớ cache hay không. Tuy nhiên, khi bạn sử dụng iterator()
, nó không kiểm tra bộ nhớ cache và đọc kết quả trực tiếp từ cơ sở dữ liệu, cũng không lưu kết quả vào bộ truy vấn.
Bây giờ, bạn phải tự hỏi làm thế nào điều này là hữu ích. Hãy xem xét một bộ truy vấn trả về một số lượng lớn các đối tượng với nhiều bộ nhớ để lưu vào bộ nhớ cache nhưng chỉ được sử dụng một lần, trong trường hợp này, bạn nên sử dụng một iterator()
.
queryset = Product.objects.all() for each in queryset: do_something(each)
Trong khi nếu chúng ta sử dụng iterator()
, Django sẽ giữ kết nối SQL mở và đọc từng bản ghi và gọi do_something()
trước khi đọc bản ghi tiếp theo:
queryset = Product.objects.all().iterator() for each in queryset: do_something(each)
Django tạo một kết nối cơ sở dữ liệu mới cho mỗi yêu cầu và đóng nó sau khi yêu cầu hoàn tất. Hành vi này do CONN_MAX_AGE
gây ra, có giá trị mặc định là 0. Nhưng nó phải được đặt thành bao lâu? Điều đó được xác định bởi khối lượng lưu lượng truy cập trên trang web của bạn; âm lượng càng cao thì càng cần nhiều giây để duy trì kết nối. Bạn nên bắt đầu bằng một số thấp, chẳng hạn như 60.
Bạn cần bao gồm các tùy chọn bổ sung của mình trong OPTIONS
, như được trình bày chi tiết trong
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dashboard', 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'CONN_MAX_AGE': '60', } } }
Lưu ý: Các biểu thức này được định nghĩa trong django.db.models.expressions
và django.db.models.aggregates
, nhưng để thuận tiện, chúng có sẵn và thường được nhập từ django.db.models
.
Trong API truy vấn Django, biểu thức F()
được sử dụng để tham chiếu trực tiếp đến các giá trị trường mô hình. Nó cho phép bạn tham chiếu đến các giá trị trường mô hình và thực hiện các hành động cơ sở dữ liệu trên chúng mà không cần phải tìm nạp chúng từ cơ sở dữ liệu và vào bộ nhớ Python. Thay vào đó, Django sử dụng đối tượng F()
để tạo ra một cụm từ SQL xác định hoạt động cơ sở dữ liệu cần thiết.
products = Product.objects.all() for product in products: product.price *= 1.2 product.save()
Tuy nhiên, nếu chúng ta sử dụng F()
, chúng ta có thể thực hiện việc này trong một truy vấn duy nhất như sau:
from django.db.models import F Product.objects.update(price=F('price') * 1.2)
select_related()
và prefetch_related()
Django cung cấp các đối số select_related()
và prefetch_related()
để tối ưu hóa các tập truy vấn của bạn bằng cách giảm thiểu số lượng yêu cầu cơ sở dữ liệu.
select_related()
"theo sau" các mối quan hệ khóa ngoại, chọn dữ liệu đối tượng có liên quan bổ sung khi nó thực hiện truy vấn của nó.
prefetch_related()
thực hiện tìm kiếm riêng biệt cho từng mối quan hệ và thực hiện "tham gia" trong Python.
select_related()
Chúng tôi sử dụng select_related()
khi mục được chọn là một đối tượng duy nhất có nghĩa là chuyển tiếp trường ForeignKey
, OneToOne
và OneToOne
ngược.
Bạn có thể sử dụng select_related()
để tạo một truy vấn duy nhất trả về tất cả các đối tượng liên quan cho một trường hợp duy nhất cho các kết nối một-nhiều và một-một. Khi truy vấn được thực hiện, select_related()
truy xuất bất kỳ dữ liệu đối tượng liên quan bổ sung nào từ các mối quan hệ khóa ngoại.
select_related()
hoạt động bằng cách tạo một phép nối SQL và bao gồm các cột của đối tượng liên quan trong biểu thức SELECT
. Kết quả là select_related()
trả về các mục có liên quan trong cùng một truy vấn cơ sở dữ liệu.
Mặc dù select_related()
tạo ra một truy vấn phức tạp hơn, dữ liệu thu được được lưu vào bộ nhớ đệm, do đó việc xử lý dữ liệu thu được không cần bất kỳ yêu cầu cơ sở dữ liệu bổ sung nào.
queryset = Tweet.objects.select_related('owner').all()
prefetch_related()
Ngược lại, prefetch_related()
được sử dụng cho các kết nối nhiều-nhiều và nhiều-một. Nó tạo ra một truy vấn duy nhất bao gồm tất cả các mô hình và bộ lọc được đưa ra trong truy vấn.
Book.objects.prefetch_related('author').get(id=1).author.first_name
Đọc chi tiết về sự khác biệt giữa select_related()
và prefetch_related()
tại .
bulk_create()
và bulk_update()
bulk_create()
là một phương thức tạo danh sách các đối tượng được cung cấp vào cơ sở dữ liệu bằng một truy vấn. Tương tự, bulk_update()
là một phương thức cập nhật các trường nhất định trên các cá thể mô hình được cung cấp bằng một truy vấn.
class Post(models.Model): title = models.CharField(max_length=300, unique=True) time = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title
Bây giờ, giả sử chúng ta muốn thêm nhiều bản ghi dữ liệu vào mô hình này, sau đó chúng ta có thể sử dụng bulk_create()
như sau:
#articles articles = [Post(title="Hello python"), Post(title="Hello django"), Post(title="Hello bulk")] #insert data Post.objects.bulk_create(articles)
>>> Post.objects.all() <QuerySet [<Post: Hello python>, <Post: Hello django>, <Post: Hello bulk>]>
Và nếu chúng ta muốn cập nhật dữ liệu, thì chúng ta có thể sử dụng bulk_update()
như sau:
update_queries = [] a = Post.objects.get(id=14) b = Post.objects.get(id=15) c = Post.objects.get(id=16) #set update value a.title="Hello python updated" b.title="Hello django updated" c.title="Hello bulk updated" #append update_queries.extend((a, b, c)) Post.objects.bulk_update(update_queries, ['title'])
>>> Post.objects.all() <QuerySet [<Post: Hello python updated>, <Post: Hello django updated>, <Post: Hello bulk updated>]>