Django использует аннотирование вместо Distinct () - PullRequest
1 голос
/ 26 августа 2011

Я читал, что вызов API Different () иногда вызывает проблемы с производительностью.Я хотел попытаться переписать запрос через форму, которая избегала использования различных (по крайней мере, профилировать разницу).

Насколько я понимаю, values ​​() выполняет Group By под капотом.Когда я тестирую два метода, количество объектов различается в зависимости от того, использую ли я Different () или values ​​() / annotate ().

   zip_codes = Location.objects.values('zip_code').annotate(zip_count=Count('zip_code')).exclude(zip_code=None).count()

VS.

  zip_codes = Location.objects.values_list('zip_code', flat=True).exclude(zip_code=None).distinct()

есть мысли о том, что здесь не так?

Спасибо!

1 Ответ

2 голосов
/ 26 августа 2011

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

Я бы тоже СКОРО скептически отнесся к предпосылке. DISTINCT - это действительно интенсивный запрос процессора. Однако, так же, как и COUNT (*), и ваш второй запрос сначала выполнит агрегат подсчета с группой, а затем выполнит COUNT для результатов. Я бы положил деньги на то, чтобы один вызов DISTINCT был быстрее (я бы также посоветовался с тем, какой сервер базы данных вы используете для просмотра). Все это имеет очень мало общего с ORM в django и чертовски много общего с вашей базой данных.

Тоже подумай об этом. Отличный основанный запрос на порядок более ясен относительно того, что он выполняет, по сравнению с основанным на аннотации запросом. Есть ли у вас доказательства, подтверждающие, что DISTINCT будет медленным в вашей ситуации, или, что еще лучше, он сейчас создает узкое место? Если нет, то вы находитесь в диапазоне преждевременной оптимизации и должны серьезно пересмотреть свой путь.

Преждевременная оптимизация .

Оптимизация имеет значение только тогда, когда она имеет значение. Когда это важно, это имеет большое значение, но пока вы не знаете, что это важно, не тратьте много времени на это. Даже если вы знаете, что это важно, вам нужно знать, где это важно. Без данных о производительности вы не будете знать, что оптимизировать, и, вероятно, оптимизируете не то.

Результат будет неясным, трудным для написания, трудным для отладки и трудным в обслуживании кода, который не решит вашу проблему. Таким образом, он имеет двойной недостаток: (а) увеличение затрат на разработку и обслуживание программного обеспечения и (б) отсутствие какого-либо влияния на производительность.

Другими словами, пишите свое программное обеспечение четко, а затем, когда вы обнаружите проблему, отследите ее до источника и исправьте. Все, что вы делаете до этого, контрпродуктивно. Потратьте свое время на размышления о том, какие индексы будут иметь значение для вашей базы данных и где использовать select_related. Это на 10000% эффективнее, чем то, о чем вы здесь беспокоитесь (если вы не учитываете почтовые индексы все время, в этом случае позвольте мне познакомить вас с кэшированием)

...