Найти - Пользователи
Полная версия: производительность lazy и обычных запросов.
Начало » Django » производительность lazy и обычных запросов.
1
Atterratio
Кто ни будь знает, при большом объёме быза данных производительность lazy запросов отличается от производительности обычных? То есть будет ли разница и в чью пользу по скорости между:

a = Model.objects.filter(p1='s1').filter(p2='s2').filter(p3='s3')
b = Model.objects.all()
b = b.filter(p1='s1')
b = b.filter(p2='s2')
b = b.filter(p3='s3')
svas
По-моему между a и b никакой разницы. Запрос к базе ни в том ни в другом случае пока не выполнялся.
https://docs.djangoproject.com/en/1.4/ref/models/querysets/#when-querysets-are-evaluated
Imposeren
lazy:

for item in Model.objecta.filter(p1='s1'):
    pass


not lazy (but all is in memory!)
for item in list(Model.objecta.filter(p1='s1')):
    pass

замечу что второй способ часто в разы быстрее, но и требовательнее к памяти
svas
Объясните в чем разница, кроме преобразования QuerySet в list?
fata1ex
При преобразовании мы проходимся по QuerySet'у, а значит пользы от того, что это генератор, никакой. Это как range vs xrange.

Документация:
list().
Force evaluation of a QuerySet by calling list() on it. For example:
entry_list = list(Entry.objects.all())
Be warned, though, that this could have a large memory overhead, because Django will load each element of the list into memory. In contrast, iterating over a QuerySet will take advantage of your database to load data and instantiate objects only as you need them.
kmike
Вот это:
for item in Model.objects.filter(p1='s1'):
    pass
точно так же загрузит все данные в память. Запрос выполнится сразу, как начнется итерация; результат (весь) попадет из сервера БД в питоний драйвер БД (может что-то поменялось, но раньше большая часть драйверов БД не поддерживали постепенное получение результатов, или джанга их так использовала). А потом джанга будет создавать экземпляры модели постепенно (и запоминать/кешировать их). Отличие от варианта с list() в том, что при варианте с list() все экземпляры моделей создадутся сразу. Короче, непонятно, отчего способ с list() может быть в разы быстрее, или требовать больше памяти, тут по сути одно и то же происходит. Мне кажется, @Imposeren что-то путает тут.

Чтоб не кешировать экземпляры моделей, можно использовать вот такую конструкцию:
for item in Model.objects.filter(p1='s1').iterator():
    pass
вот это будет требовать меньше памяти, т.к. экземпляры моделей внутри кверисета кешироваться не будут. Это означает, например, что при повторной итерации будет выполнен еще один sql-запрос. Ну и с этим способом все равно можно потратить много памяти (хотя и меньше, чем без .iterator()), если драйвер БД (и его связка с джангой) не поддерживает итерацию, а вытаскивает с сервера все сразу.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB