2011-11-26 7 views
7

He tenido una consulta que ha estado funcionando bien durante aproximadamente 2 años. La tabla de la base de datos tiene aproximadamente 50 millones de filas, y está creciendo lentamente. La semana pasada, una de mis consultas pasó de regresar casi instantáneamente a tomar horas para ejecutarse.Consulta simple de trabajo durante años, luego de repente muy lento

Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)).latest('id') 

He reducido la consulta lenta al modelo de rango. Parece tener algo que ver con el uso del último método(). Si solo solicito un conjunto de consulta, devuelve un conjunto de consulta vacío de inmediato.

#count returns 0 and is fast 
Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)).count() == 0 
Rank.objects.filter(site=Site.objects.get(profile__client=client, profile__is_active=False)) == [] #also very fast 

Aquí están los resultados de ejecutar EXPLAIN. http://explain.depesz.com/s/wPh

y explicar ANALIZAR: http://explain.depesz.com/s/ggi

traté de aspirar la mesa, no hay cambio. Ya hay un índice en el campo "sitio" (ForeignKey).

Extrañamente, si ejecuto esta misma consulta para otro cliente que ya tiene objetos de rango asociados a su cuenta, la consulta vuelve muy rápido una vez más. Entonces parece que esto es solo un problema cuando no hay objetos Rank para ese cliente.

¿Alguna idea?

Versiones: Postgres 9.1, 1.4 Django tronco svn rev 17047

Respuesta

0

Bueno, no has mostrado el SQL real, por lo que es difícil estar seguro. Sin embargo, el resultado de la explicación sugiere que cree que la forma más rápida de encontrar una coincidencia es escaneando un índice en "id" hacia atrás hasta que encuentre al cliente en cuestión.

Como dijo que ha sido rápido hasta hace poco, esta probablemente no es una elección tonta. Sin embargo, siempre existe la posibilidad de que el registro de un cliente en particular esté justo al final de esta búsqueda.

Por lo tanto - probar dos cosas primero:

  1. Ejecutar un analizan en la tabla en cuestión, ver si se da el planificador de información suficiente.
  2. De lo contrario, aumente las estadísticas (ALTER TABLE ... SET STATISTICS) en las columnas en cuestión y vuelva a analizarlas. Ve si eso lo hace.

http://www.postgresql.org/docs/9.1/static/planner-stats.html

Si eso todavía no ayudar, y luego considerar un índice en (cliente, id), y quitar el índice de Identificación (si no es necesario en otros lugares). Eso debería darte respuestas rapidísimas.

+0

La configuración de un índice compuesto en el campo en el DONDE, así como el campo en ORDEN POR hizo el truco. Resulta que el planificador de consultas estaba escaneando todo el índice para el orden y luego haciendo el filtro. El índice compuesto hizo el truco. – erikcw

0

latests se utiliza normalmente para la comparación de fechas, tal vez debería tratar de ordenar por desc Identificación y luego limitar a uno.

+0

Lo intenté y también hubo un retraso similarmente largo. Cuando miro el SQL sin procesar generado por el ORM, ambos producen resultados equivalentes. – erikcw