Django - применение своих SQL запросов

Проблема

Недавно на одном сайте, мне нужно было получить большое количество объектов модели одного типа.

Сначала написал такой вот код:

# Получить объекты модели 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

Это получается, что если мне нужно для одной HTML страницы получить информацию из 50-ти строк таблицы БД, будет сгенерировано 50 SQL запросов. Каждый запрос будет послан в БД и ответ получен. Для простейших случаев и не нагруженных сайтов годится, для нагруженных сайтов не очень.

Почему бы не применить традиционный путь, принятый в работе с БД? Выбрать одним запросом все строки, которые мне нужны, затем вытащить в программу все полученные результаты.

Решение

Сказано - сделано. Посмотрел в документацию Django. Все оказалось не просто, а очень просто.

Написал метод, которая тянет из БД нужную информацию в один прием. Метод получился весьма простым:

  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

Проверка эффективности

Сравнение проводилось при помощи django-debug-toolbar. Вот результаты:

Количество
элементов
на странице
Количество запросов Среднее время генерации страницы
Код, работающий через API модели 12 13 ~300 ms
Код с кастомным SQL 12 1 ~150 ms

Вывод

В определенных случаях, например как в описанном, когда нужно получать много строк из одной таблицы и если необходима производительность, в Django есть смысл использовать процедуры, напрямую получающие информацию из БД, не используя API модели.

Опубликовано: September 5, 2010

Комментарии:


Имя: анзор

просто взять и запрос написать хорошо конечно, но хотелось бы делать это в рамках архитектуры фреймворка, раз уж он используется. ведь на сколько знаю алгоритм выборки того же "mt = MsgText.objects.filter(msg__page__name=page,lang__name=lang)" можно кастомизировать в манагере модели MsgText



Комментировать:

Имя:

Комментарий: