Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » Получить из базы сразу отфильтрованный набор объектов. [RSS Feed]

#1 Авг. 30, 2010 23:15:21

f_evgeny
От:
Зарегистрирован: 2010-08-16
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

Разбираюсь с Django. Написал что-то вроде

        # Получить обекты модели MsgTxt, которые нам нужны
mt = MsgText.objects.filter(msg__page__name=page,lang__name=lang)
# Упаковать полученную информацию в словарь
out = {}
for ob in mt:
out[ob.msg.name] = ob.text
return out
ПосмотрелSQL, на каждый объект в цикле генерится отдельный SQL запрос.
типа:
SELECT ..... WHERE "multilang_msg"."id" = 14
Поискал и не нашел способа получить сразу все объекты одним SQL запросом. А у меня на странице таких записей может быть много. Как-то не хочется иметь сотню запросов на страницу.
Я правильно понимаю, что тут нужно испольpовать кастомный SQL запрос, не испольуя ORM?

Спасибо



Офлайн

#2 Авг. 31, 2010 08:12:49

cybergrind
От:
Зарегистрирован: 2008-01-21
Сообщения: 201
Репутация: +  0  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

Офлайн

#3 Авг. 31, 2010 12:27:01

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

f_evgeny
Поискал и не нашел способа получить сразу все объекты одним SQL запросом
mt = list(MsgText.objects.filter(msg__page__name=page,lang__name=lang))



Офлайн

#4 Авг. 31, 2010 16:27:31

f_evgeny
От:
Зарегистрирован: 2010-08-16
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

cybergrind
стоит прочитать про
http://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy
ну и как возможный путь решения
http://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related
Посмотрел, это не совсем то.



Офлайн

#5 Авг. 31, 2010 16:38:31

f_evgeny
От:
Зарегистрирован: 2010-08-16
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

regall
f_evgeny
Поискал и не нашел способа получить сразу все объекты одним SQL запросом
mt = list(MsgText.objects.filter(msg__page__name=page,lang__name=lang))
Это не то, количество запросов не уменьшается, просто генерятся они не в цикле, а во время выполнения list()
Проблему не снимает.



Офлайн

#6 Авг. 31, 2010 16:49:30

f_evgeny
От:
Зарегистрирован: 2010-08-16
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

Короче, сделал так:

    def get_msgs(self,page,lang):
from django.db import connection, transaction
cursor = connection.cursor()
cursor.execute("""
SELECT msg.name,mst.text
FROM multilang_msgtext AS mst, multilang_msg AS msg,
multilang_page AS mp, multilang_lang as ml
WHERE mst.lang_id=ml.id AND mst.msg_id=msg.id AND msg.page_id=mp.id
AND ml.name=%s AND mp.name=%s;
""",(lang,page))
out = {}
while(1):
row = cursor.fetchone()
if(row == None):
break
out[row[0]] = row[1]
return out
Результаты тестирования:
                    Количество                       Количество             Среднее время
элементов запросов генерации страницы
Старый код: 12 13 ~300ms
Новый код: 12 1 ~150ms



Офлайн

#7 Авг. 31, 2010 18:54:43

cybergrind
От:
Зарегистрирован: 2008-01-21
Сообщения: 201
Репутация: +  0  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

ну судя по запросу это как раз и есть случай который описывается в ленивых кверисетах, дергается каждый раз объект из другой модели, и на каждый такой вызов выполняется запрос к базе данных.



Офлайн

#8 Авг. 31, 2010 20:33:51

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

f_evgeny
Я правильно понимаю, что тут нужно испольpовать кастомный SQL запрос, не испольуя ORM?
Нет.

msg это ForeignKey? Тогда конечно надо читать документацию и использовать select_related. А про SQL забыть.



Офлайн

#9 Сен. 2, 2010 17:30:33

f_evgeny
От:
Зарегистрирован: 2010-08-16
Сообщения: 20
Репутация: +  1  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

Да дело-то не в том, что значения по ForeignKey тащатся отдельными запросами. Данный код должен вытыщить несколько строк таблицы. Дело в том, что код получается работает в два этапа:
1) Составляется довольно-таки грамотный запрос, учитывающий связи, и все, что нужно. Этот запрос возвращает итерабильный QuerySet.
2) При запросе во время очередной итерации следующего элемента, QuerySet генерирует ОДИН SQL запрос и тащит ОДНУ строку из таблицы, по ‘id’. И так каждый раз.
В случае, когда для формирования вебстраницы нужно из одной таблицы вытащить штук 50 строк, это все может быть затратным.
Если посмотреть в потроха, выглядит все это примерно так:
Первый запрос, возвращающий QuerySet

SELECT "multilang_msgtext"."id", "multilang_msgtext"."lang_id", "multilang_msgtext"."msg_id", "multilang_msgtext"."text" FROM "multilang_msgtext" INNER JOIN "multilang_lang" 
ON ("multilang_msgtext"."lang_id" = "multilang_lang"."id") INNER JOIN "multilang_msg" ON ("multilang_msgtext"."msg_id" = "multilang_msg"."id")
INNER JOIN "multilang_page" ON ("multilang_msg"."page_id" = "multilang_page"."id")
WHERE ("multilang_lang"."name" = E'Russian' AND "multilang_page"."name" = E'site_header_1' )
Последующие запросы:
.....
SELECT "multilang_msg"."id", "multilang_msg"."page_id", "multilang_msg"."msgnum", "multilang_msg"."name", "multilang_msg"."comment"
FROM "multilang_msg" WHERE "multilang_msg"."id" = 20
.....
Я вижу смысл в определенных случаях (нужно много записей из одной таблицы), получить все записи одним запросом, используя самописный SQL. Это здорово экономит ресурсы, а код почти не усложняет.



Офлайн

#10 Сен. 2, 2010 19:03:33

Александр Кошелев
От: Москва
Зарегистрирован: 2007-02-03
Сообщения: 1724
Репутация: +  2  -
Профиль   Отправить e-mail  

Получить из базы сразу отфильтрованный набор объектов.

Очевидно, что вы от нас почему-то скрываете питонячий код моделей и что по этом sql запросам ничего не понятно.



Офлайн

  • Начало
  • » Django
  • » Получить из базы сразу отфильтрованный набор объектов.[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version