python - django querysets+memcached: mejores prácticas
django-cache (1)
Intentando entender qué sucede durante un django low-level cache.set () Particularmente, detalles sobre qué parte del queryset se almacena en memcached.
En primer lugar, ¿estoy interpretando los documentos django correctamente?
- un queryset (objeto python) tiene / mantiene su propio caché
- el acceso a la base de datos es perezoso; incluso si queryset.count es 1000, si hago un object.get para 1 registro, solo se accederá a dbase una vez, para ese 1 registro.
- al acceder a una vista de django a través de apache prefork MPM, cada vez que una instancia X del demonio en particular termina invocando una vista particular que incluye algo como "tournres_qset = TournamentResult.objects.all ()", esto resultará, cada vez, en una nueva Se está creando el objeto tournres_qset. Es decir, cualquier cosa que pueda haber sido almacenada en caché internamente por un objeto de python tournres_qset de una visita previa (tcp / ip), no es utilizada en absoluto por el tournres_qset de una nueva solicitud.
Ahora las preguntas sobre cómo guardar cosas para guardarlas en la vista. Digamos que agrego algo como esto en la parte superior de la vista:
tournres_qset = cache.get(''tournres'', None)
if tournres_qset is None:
tournres_qset = TournamentResult.objects.all()
cache.set(''tournres'', tournres_qset, timeout)
# now start accessing tournres_qset
# ...
¿Qué se almacena durante el cache.set ()?
¿Todo el queryset (objeto de Python) se serializa y guarda?
Dado que aún no se ha utilizado el queryset para obtener ningún registro, ¿es solo una pérdida de tiempo, ya que no se está guardando el contenido de ningún registro en particular en memcache? (Cualquier solicitud futura obtendrá el objeto queryset de memcache, que siempre comenzará de nuevo, con un caché local de consultas vacío; el acceso a la base de datos siempre ocurrirá).
Si lo anterior es cierto, entonces siempre debería volver a guardar el conjunto de consultas al final de la vista, después de que se haya utilizado en todo el vierw para acceder a algunos registros, lo que dará como resultado que la memoria caché local del queryset se actualice, y que debería siempre ser re-guardado en memcached? Pero entonces, esto siempre resultaría en una vez más serializar el objeto queryset. Tanto para acelerar las cosas.
O, ¿cache.set () obliga al objeto queryset a iterar y acceder desde la base de datos a todos los registros, que también se guardarán en memcache? ¿Se guardaría todo, incluso si la vista solo accede a un subconjunto del conjunto de consultas?
Veo trampas en todas direcciones, lo que me hace pensar que soy
malinterpretando un montón de cosas.
Espero que esto tenga sentido y aprecie las aclaraciones o los indicadores de algunas pautas "estándar". Gracias.
Los conjuntos de consultas son perezosos, lo que significa que no llaman a la base de datos hasta que se evalúan. Una forma en que podrían ser evaluados sería serializarlos, que es lo que hace cache.set
detrás de escena. Así que no, esto no es una pérdida de tiempo: todo el contenido de su modelo de torneo se almacenará en caché, si eso es lo que quiere. Probablemente no lo sea: y si sigues filtrando el conjunto de consultas, Django simplemente volverá a la base de datos, lo que hará que todo sea un poco inútil. Solo debe almacenar en caché las instancias del modelo que realmente necesita.
Tenga en cuenta que el tercer punto en su conjunto inicial no es del todo correcto, ya que esto no tiene nada que ver con Apache o preformado. Es simplemente que una vista es una función como cualquier otra, y cualquier cosa definida en una variable local dentro de una función queda fuera del alcance cuando esa función regresa. Por lo tanto, un conjunto de consultas definido y evaluado dentro de una vista queda fuera del alcance cuando la vista devuelve la respuesta, y se creará una nueva la próxima vez que se llame a la vista, es decir, en la siguiente solicitud. Este es el caso de cualquier manera que estés sirviendo a Django.
Sin embargo , y esto es importante, si hace algo como configurar su queryset a una variable global (nivel de módulo), persistirá entre las solicitudes . La mayoría de las formas en que se sirve Django, y esto definitivamente incluye mod_wsgi, mantienen un proceso activo para muchas solicitudes antes de reciclarlo, por lo que el valor de queryset será el mismo para todas esas solicitudes. Esto puede ser útil como una especie de caché de ganga, pero es difícil hacerlo bien porque no tiene idea de cuánto durará el proceso, además de otros procesos que probablemente se ejecutarán en paralelo y que tienen sus propias versiones de esa variable global. .
Actualizado para responder preguntas en el comentario.
Sus preguntas muestran que todavía no se ha quejado del funcionamiento de las consultas. Se trata de cuándo se evalúan: si enumera, o itera, o rebana un queryset, eso lo evalúa, y en ese punto se realiza la llamada a la base de datos (cuento la serialización en iteración, aquí), y los resultados almacenados en el Caché interno de Queryset. Por lo tanto, si ya ha hecho una de esas cosas en su conjunto de consultas y luego lo configura en el caché (externo), eso no causará otro impacto en la base de datos.
Pero , cada operación de filter()
en un queryset, incluso una que ya ha sido evaluada, es otro hit de la base de datos. Esto se debe a que es una modificación de la consulta SQL subyacente, por lo que Django vuelve a la base de datos y devuelve un nuevo conjunto de consultas, con su propio caché interno.