2011-04-13 7 views
6

Tengo un conjunto de consultas de aproximadamente 1500 registros de una consulta ORM de Django. He usado los métodos select_related() y only() para asegurarme de que la consulta sea estricta. También he usado connection.queries para asegurarme de que solo haya una consulta. Es decir, me he asegurado de que no se llamen consultas adicionales en cada iteración.¿Cómo puedo acelerar la iteración de grandes conjuntos de datos en Django?

Cuando ejecuto la consulta cortar y pegar desde connection.queries se ejecuta en 0.02 segundos. Sin embargo, lleva siete segundos iterar sobre esos registros y no hacer nada con ellos (pase).

¿Qué puedo hacer para acelerar esto? ¿Qué causa esta lentitud?

+0

¡Debe incluir más detalles sobre sus modelos y la consulta! –

+4

También debería escribir Django <- de esta manera :) era un guitarrista, no un DJ –

Respuesta

14

Un QuerySet puede ser bastante pesado cuando está lleno de objetos modelo. En situaciones similares, he usado el método .values ​​en el conjunto de consultas para especificar las propiedades que necesito como lista de diccionarios, que pueden ser mucho más rápidos de iterar. http://docs.djangoproject.com/en/1.3/ref/models/querysets/#values-list

+1

Tenías razón. Resulta que la creación de instancias de los objetos modelo en cada iteración estaba causando mucha sobrecarga. El uso del método de valores llevó la iteración del conjunto de siete segundos a solo unos pocos milisegundos. – stinkypyper

+1

Impresionante. Me alegro de poder ayudar. – Brandon

+0

¡Noté un gran aumento de rendimiento con esto! Estaba iterando un conjunto de consulta de 110000 elementos, que tardó casi 70 segundos en completarse. ¡Iterar la misma lista de valores tomó 5 segundos! – ninapavlich

2

1500 registros está lejos de ser un gran conjunto de datos, y siete segundos es realmente demasiado. Probablemente haya algún problema en sus modelos, puede verificarlo fácilmente obteniendo (como dice Brandon) la consulta values ​​(), y luego crear explícitamente el objeto 1500 iterando el diccionario. Simplemente convierta el ValuesQuerySet en una lista antes de la construcción para factorizar la conexión db.

2

¿Cómo estás iteración del cada elemento:

items = SomeModel.objects.all() 

regular de bucle en cada

for item in items: 
    print item 

o utilizando el QuerySet iterator

for item in items.iterator(): 
    print item 

De acuerdo con el documento, la iterator() puede mejorar el rendimiento. Lo mismo se aplica al hacer un bucle en una lista o diccionarios de Python muy grandes, es mejor usar iteritems().

+0

No estoy seguro de si esto funcionaría, ya que la iteración se realiza principalmente en la plantilla y no estoy seguro de si tenemos el .iterator() allí. – sprezzatura

+0

Lo he comprobado y en realidad está funcionando. Acelera mucho el bucle for. De 0: 00: 45.550635 a 0: 00: 09.761178, ¡por lo menos 4 veces más rápido! –

1

¿La declaración Meta de su modelo indica que "ordene por" un campo que está almacenado en alguna otra tabla relacionada? Si es así, su intento de iterar podría desencadenar 1.500 consultas mientras Django se escapa y toma ese campo para cada elemento, y luego los ordena. ¡Mostrarnos tu código nos ayudaría a resolver el problema!

Cuestiones relacionadas