ehles
@ehles

Как реализовать выборку из таблиц mysql, связанных как один ко многим?

В БД есть таблички:
BlogRecord - кол-во записей более 30 000.
Comment - кол-во записей более 250 000.
Всё реализовано на Django, модели имеют примерно следующий вид:
class BlogRecord(models.Model):
    text = models.TextField(null=True, blank=True)
    # прочие поля

class Comment(models.Model):
    blog_record = models.ForeignKey(BlogRecord, db_index=True)
    # прочие поля


Сначала делается выборки из таблицы комментариев, в выборку может попасть более 150к записей, далее нужно получить список записей в блоге из этой выборки. Проблема в том, что такой запрос выполняется непозволительно долго - более 30 сек, хотелось бы уменьшить это время секунд до 1-2.

Изначально выборку делал так:
# сложная выборка по разным полям из таблицы комментариев
comments = models.Comment.objects.filter() 
blog_record = models.BlogRecord.objects.filter(
        id__in=comments.values_list('blog_record')
    )


Потом пробовал перенести часть вычислений в код python, но лучше не стало.
comment_ids = # Большой список ID комментариев полученный в результате выборки.
models.BlogRecord.objects.filter(id__in=comment_ids)


Может есть какие ещё методы, может изменить что-то в структуре БД?

P.S. В django не очень силен, возможно что-то делаю не так.
  • Вопрос задан
  • 3425 просмотров
Решения вопроса 1
@yamel
Можно попробовать условия выборки комментариев перенести во второй запрос.
Например, так:
blog_record = models.BlogRecord.objects.filter(comment__author=103, comment__status='publish')
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@maxfox
Не совсем понял, что вы хотите сделать, но это точно надо делать в один запрос.
"Перенося часть вычислений в код Python" вы только тормозите процесс. Быстрее всего выборка производится на стороне СУБД - она написана на C и максимально оптимизирована. Поэтому, чтобы вы там не делали, старайтесь уложить это в один запрос.

Опишите, какой результат вы хотите получить, тогда будет проще подсказать.
Ответ написан
ehles
@ehles Автор вопроса
Сделал как посоветовал @yamel:
comment_params = {"comment__author":103}
blog_records = models.BlogRecord.objects.filter(
     **comment_params
     ).annotate(Count('comment__blogrecord'))


Всем спасибо!!!

Да, вот результат, тестировал на небольшом запросе:
было 50сек, стало 0.9 сек.

P.S. с кол-вом записей немного наврал, их больше на порядок.)))
P.P.S. попутно нашел ещё багу что тормозила выполнение запросов вкурив в то какие SQL запросы генерит django.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы