Джанго: Как мне избежать ненужных операторов SQL? - PullRequest
2 голосов
/ 14 марта 2012

Я оптимизирую медленную загрузку страницы в нашем (первом) проекте Django. Общий проект проверяет управление состоянием, поэтому существуют протоколы, в которых есть дела, для которых запланировано выполнение. В настоящее время код:

protocols = Protocol.active.filter(team=team, release=release)
cases = Case.active.filter(protocol__in=protocols)
caseCount = cases.count()
plannedExecs = Planned_Exec.active.filter(case__in=cases, team=team, release=release)

# Start aggregating test suite information 
# pgi Model
testSuite['pgi_model'] = []
for pgi in PLM.objects.filter(release=release).values('pgi_model').distinct():
    plmForPgi = PLM.objects.filter(pgi_model=pgi['pgi_model'])
    peresults = plannedExecs.filter(plm__in=plmForPgi).count()
    if peresults > 0:
        try:
            testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, int(peresults/float(testlistCount)*100)))
        except ZeroDivisionError:
            testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, 0))

# Browser
testSuite['browser'] = []
for browser in BROWSER_OPTIONS:
    peresults = plannedExecs.filter(browser=browser[0]).count()
    try:
        testSuite['browser'].append((browser[1], "", "", peresults, int(peresults/float(testlistCount)*100)))
    except ZeroDivisionError:
        testSuite['browser'].append((browser[1], "", "", peresults, 0))

# ... more different categories are aggregated below, then the report is generated...

Этот код делает много SQL-операторов. PLM.objects.filter(release=release).values('pgi_model').distinct() возвращает список из 50 строк, и обе операции фильтра выполняют SQL-оператор для каждой строки, что означает 100 SQL-операторов только для цикла for. (Кроме того, похоже, что следует использовать values_list с flat=True.)

Поскольку я хочу получить информацию о соответствующих делах и планируемых исполнениях, я думаю, что мне действительно нужно только извлечь эти две таблицы, а затем провести некоторый анализ по этому вопросу. Использование filter и count () в то время казалось очевидным решением, но мне интересно, не лучше ли мне было бы просто составить изложение соответствующего случая и информации планируемого выполнения с использованием .values ​​(), а затем проанализировать это, поэтому как избежать ненужных операторов SQL. Любой полезный совет? Спасибо!

Редактировать: В попытке профилировать это, чтобы понять, куда идет время, я использую панель инструментов Django Debug. Это объясняет, что существует более 200 запросов, каждый из которых выполняется очень быстро, поэтому в целом они занимают очень мало времени. Однако может ли быть так, что выполнение SQL выполняется относительно быстро, но сборка ORM складывается, учитывая, что это происходит более 200 раз? Я произвел рефакторинг предыдущей страницы, загрузка которой заняла 3 минуты, и использовал values ​​() вместо ORM, таким образом снизив загрузку страницы до 2,7 секунды и 5 операторов SQL.

Ответы [ 2 ]

1 голос
/ 14 марта 2012

Это выглядит как случай для обратного поиска по внешнему ключу. Мы должны быть в состоянии уменьшить цикл top путем получения всех pgi_models, связанных с PLM, в релизе. Я предполагаю, что у вас есть модель для PGI, для которой модель PLM имеет поле внешнего ключа с именем pgi_model. Если это так, вы можете найти PGI в выпуске PLM со следующим. У вас все еще есть цикл, но итерации цикла теоретически должны быть сокращены:

pgis = PGI.objects.filter(plm__in=PLM.objects.filter(release=release))
for pgi in pgis:
    peresults = plannedExecs.filter(plm=pgi.plm).count()
    if peresults > 0:
        try:
            testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, int(peresults/float(testlistCount)*100)))
        except ZeroDivisionError:
            testSuite['pgi_model'].append((pgi['pgi_model'], "", "", peresults, 0))
1 голос
/ 14 марта 2012

Создание набора запросов не попадает в базу данных;делает доступ только к результатам.Соответственно, просто создание наборов запросов не является вашей проблемой.

Обратите внимание, что передача набора запросов в другой набор запросов не создает два запроса.Соответственно, создание диктов не уменьшит количество обращений к базе данных.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...