Để lưu trữ bộ đệm thẳng của một đối tượng đã được tải, vâng, bạn không thu được gì hoặc không có gì. Đó không phải là những gì những ví dụ đó đang mô tả - họ đang mô tả một hệ thống phân cấp, trong đó bất kỳ thay đổi nào đối với thứ gì đó thấp hơn cũng sẽ kích hoạt một bản cập nhật cho mọi thứ cao hơn trong hệ thống phân cấp.
Ví dụ đầu tiên, từ blog 37signals, sử dụng Project -> Todolist -> Todo
làm hệ thống phân cấp. Một ví dụ dân cư có thể trông như thế này:
Project: Foo (last_modified: 2014-05-10)
Todolist: Bar1 (last_modified: 2014-05-10)
Todo: Bang1 (last_modified: 2014-05-09)
Todo: Bang2 (last_modified: 2014-05-09)
Todolist: Bar2 (last_modified: 2014-04-01)
Todo: Bang3 (last_modified: 2014-04-01)
Todo: Bang4 (last_modified: 2014-04-01)
Vì vậy, hãy nói rằng Bang3
đã được cập nhật. Tất cả cha mẹ của nó cũng được cập nhật:
Project: Foo (last_modified: 2014-05-16)
Todolist: Bar2 (last_modified: 2014-05-16)
Todo: Bang3 (last_modified: 2014-05-16)
Sau đó, khi đến lúc kết xuất, việc tải Project
từ cơ sở dữ liệu về cơ bản là không thể tránh khỏi. Bạn cần một điểm để bắt đầu tại. Tuy nhiên, vì đây last_modified
là chỉ báo cho tất cả các con của nó , đó là những gì bạn sử dụng làm khóa bộ đệm trước khi thử tải các con.
Trong khi các bài đăng trên blog sử dụng các mẫu riêng biệt, tôi sẽ gộp chúng lại thành một mẫu. Hy vọng nhìn thấy sự tương tác hoàn toàn ở một nơi sẽ làm cho nó rõ ràng hơn một chút.
Vì vậy, mẫu Django có thể trông giống như thế này:
{% cache 9999 project project.cache_key %}
<h2>{{ project.name }}<h2>
<div>
{% for list in project.todolist.all %}
{% cache 9999 todolist list.cache_key %}
<ul>
{% for todo in list.todos.all %}
<li>{{ todo.body }}</li>
{% endfor %}
</ul>
{% endcache %}
{% endfor %}
</div>
{% endcache %}
Giả sử chúng ta vượt qua trong một Dự án cache_key
vẫn còn tồn tại trong bộ đệm. Vì chúng tôi tuyên truyền các thay đổi cho tất cả các đối tượng liên quan đến cha mẹ, thực tế là khóa cụ thể đó vẫn tồn tại có nghĩa là toàn bộ nội dung được hiển thị có thể được kéo từ bộ đệm.
Nếu Dự án cụ thể đó vừa được cập nhật - ví dụ như Foo
ở trên - thì nó sẽ phải kết xuất con của nó và chỉ sau đó nó mới chạy truy vấn cho tất cả Todolists cho Dự án đó. Tương tự như vậy đối với một Todolist cụ thể - nếu cache_key của danh sách đó tồn tại, thì các todos bên trong nó không thay đổi và toàn bộ có thể được lấy từ bộ đệm.
Cũng lưu ý cách tôi không sử dụng todo.cache_key
trong mẫu này. Điều đó không đáng, vì như bạn nói trong câu hỏi, body
đã được lấy từ cơ sở dữ liệu. Tuy nhiên, lượt truy cập cơ sở dữ liệu không phải là lý do duy nhất bạn có thể lưu trữ một cái gì đó. Ví dụ: lấy văn bản đánh dấu thô (chẳng hạn như những gì chúng ta nhập vào hộp câu hỏi / câu trả lời trên StackExchange) và chuyển đổi nó thành HTML có thể mất đủ thời gian để lưu trữ kết quả sẽ hiệu quả hơn.
Nếu đúng như vậy, vòng lặp bên trong trong mẫu có thể trông giống như thế này:
{% for todo in list.todos.all %}
{% cache 9999 todo todo.cache_key %}
<li>{{ todo.body|expensive_markup_parser }}</li>
{% endcache %}
{% endfor %}
Vì vậy, để kết nối mọi thứ lại với nhau, hãy quay lại dữ liệu gốc của tôi ở đầu câu trả lời này. Nếu chúng ta giả sử:
- Tất cả các đối tượng đã được lưu trữ trong trạng thái ban đầu của họ
Bang3
vừa được cập nhật
- Chúng tôi đang kết xuất mẫu đã sửa đổi (bao gồm
expensive_markup_parser
)
Sau đó, đây là cách mọi thứ sẽ được tải:
Foo
được lấy từ cơ sở dữ liệu
Foo.cache_key
(2014-05-16) không tồn tại trong bộ đệm
Foo.todolists.all()
được truy vấn: Bar1
và Bar2
được lấy từ cơ sở dữ liệu
Bar1.cache_key
(2014-05-10) đã tồn tại trong bộ đệm ; lấy và xuất nó
Bar2.cache_key
(2014-05-16) không tồn tại trong bộ đệm
Bar2.todos.all()
được truy vấn: Bang3
và Bang4
được lấy từ cơ sở dữ liệu
Bang3.cache_key
(2014-05-16) không tồn tại trong bộ đệm
{{ Bang3.body|expensive_markup_parser }}
Được hiển thị
Bang4.cache_key
(2014-04-01) đã tồn tại trong bộ đệm ; lấy và xuất nó
Tiết kiệm từ bộ đệm trong ví dụ nhỏ này là:
- Cơ sở dữ liệu nhấn tránh:
Bar1.todos.all()
expensive_markup_parser
tránh 3 lần: Bang1
, Bang2
, vàBang4
Và tất nhiên, lần sau nó được xem, Foo.cache_key
sẽ được tìm thấy, do đó, chi phí duy nhất để kết xuất là lấy Foo
một mình từ cơ sở dữ liệu và truy vấn bộ đệm.