Таблица Django с миллионом строк

У меня есть проект с 2 приложениями (книги и читалка).

Приложение Books имеет таблицу с 4 миллионами строк с этими полями:

 book_title = models.CharField(max_length=40)
 book_description = models.CharField(max_length=400)

Чтобы не запрашивать базу данных с 4 миллионами строк, я думаю разделить ее по темам (20 моделей с 20 таблицами с 200 000 строк (book_horror, book_drammatic, ecc).

В приложении "читатель" я думаю вставить эти поля:

reader_name = models.CharField(max_length=20, blank=True)
book_subject = models.IntegerField()
book_id = models.IntegerField()

Поэтому вместо ForeignKey я думаю использовать целое число «book_subject» (что позволяет получить доступ к соответствующей таблице) и «book_id» (что позволяет получить доступ к книге в таблице, указанной в «book_subject»).

Является ли хорошим решением избежать запроса таблицы с 4 миллионами строк?

Есть ли альтернативное решение?

Спасибо ^__^


person xRobot    schedule 12.01.2010    source источник
comment
4 миллиона это не много, у вас преждевременная оптимизация.   -  person Tobu    schedule 12.01.2010
comment
Таблица запрашивается из ajax с использованием поля автозаполнения с этим запросом в views.py: books.objects.filter(book_title__istartswith=request.GET['q'])[:100]   -  person xRobot    schedule 12.01.2010
comment
Если вы запрашиваете таблицу в текстовом поле и производительность является проблемой, вы можете реализовать полнотекстовый поиск. Однако размер вашего запрошенного поля составляет всего 40 символов, и я не уверен, что это создает большую проблему для базы данных.   -  person shanyu    schedule 12.01.2010
comment
Это не тот вопрос, который вы задали, но он может оказаться полезным: изменения производительности запросов"> stackoverflow.com/questions/1566717/   -  person Tobu    schedule 12.01.2010


Ответы (6)


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

Индексы - это первый шаг, хотя похоже, что вы это сделали. 4 миллиона строк должны быть в порядке, чтобы БД могла обрабатывать индекс.

Во-вторых, проверьте количество запросов, которые вы выполняете. Вы можете сделать это с помощью чего-то вроде панели инструментов отладки django, и вы часто будете удивлены, сколько ненужных запросов будет сделано.

Кэширование — это следующий шаг, используйте memcached для страниц или частей страниц, которые не изменяются для большинства пользователей. Именно здесь вы увидите самый большой прирост производительности при минимальных усилиях.

Если вам действительно нужно разделить таблицы, последняя версия django (1.2 alpha) может справиться с сегментированием (например, с несколькими базами данных), и вы должны быть в состоянии вручную написать решение для горизонтального разделения (postgres предлагает in-db способ сделать это). Пожалуйста, не используйте жанр, чтобы разделить столы! выберите что-то, что вы никогда не будете менять и что вы всегда будете знать, делая запрос. Лайкнуть автора и разделить по первой букве фамилии или что-то в этом роде. Это требует больших усилий и имеет ряд недостатков для базы данных, которая не особенно велика — вот почему большинство людей здесь советуют против этого!

[редактировать]

Я упустил денормализации! Поместите общие подсчеты, суммы и т. д., например, в таблицу авторов, чтобы предотвратить объединение по общим запросам. Недостатком является то, что вы должны поддерживать его самостоятельно (пока django не добавит DenormalizedField). Я бы посмотрел на это во время разработки для ясных, простых случаев или после того, как кэширование подвело вас --- но хорошо перед сегментированием или горизонтальным разделением.

person Will Hardy    schedule 12.01.2010
comment
Хорошо, если я разделю таблицу, я разделю ее по первой букве... действительно, это более разумно :) Таблица запрашивается из ajax с использованием поля автозаполнения с этим запросом в views.py: books.objects.filter(book_title__istartswith =request.GET['q'])[:100] Итак, вы рекомендуете мне index + memcached? Спасибо - person xRobot; 12.01.2010
comment
Сделайте индекс для первых трех букв названия (или любого другого числа, с которого вы начнете запрашивать базу данных), и оно будет работать довольно быстро. - person naivists; 12.01.2010

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

Изменить: И ради всего святого, держите его в одной таблице и используйте соответствующие индексы.

person Ignacio Vazquez-Abrams    schedule 12.01.2010
comment
Я использую индекс, но в таблице 4 миллиона строк, и к ней часто обращаются. Поэтому я не знаю, достаточно ли индекса :-\ - person xRobot; 12.01.2010
comment
Если это не так, то базе данных требуется больше памяти. - person Ignacio Vazquez-Abrams; 12.01.2010
comment
4 миллиона строк — это не пустяк, но базы данных созданы для таких вещей, особенно если вы индексируете. Я бы беспокоился об этом только в том случае, если вы получаете не менее ста миллионов строк. - person LeafStorm; 13.01.2010

Я не знаком с Django, но имею общее представление о БД.

При наличии больших баз данных вполне нормально индексировать базу данных. Таким образом, получение данных должно быть довольно быстрым.

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

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

person Steven    schedule 12.01.2010
comment
20 приложений означают 20 таблиц :) Я уже использую индекс, но в таблице 4 миллиона строк, и к ней часто обращаются. Поэтому я не знаю, достаточно ли индекса :-\ - person xRobot; 12.01.2010
comment
Боги нет! Не разбивайте его на 20 таблиц! Составьте диаграмму EAR ваших таблиц, и вы увидите, какая дополнительная таблица вам нужна, чтобы справиться с этим. Например. дополнительные таблицы для привязки человека к книге, категории к книге и так далее. - person Steven; 12.01.2010

У вас проблемы с производительностью? Если это так, вам может потребоваться добавить несколько индексов.

Один из способов получить представление о том, где может помочь индекс, — просмотреть журнал запросов вашего сервера БД (здесь, если вы используете MySQL).

Если у вас нет проблем с производительностью, просто используйте его. Базы данных предназначены для обработки миллионов записей, а django довольно хорошо генерирует разумные запросы.

person Seth    schedule 12.01.2010
comment
Да, проблема с производительностью. Я использую индекс, но в таблице 4 миллиона строк, и к ней часто обращаются. Поэтому я не знаю, достаточно ли индекса :-\ - person xRobot; 12.01.2010
comment
Вероятно, лучше использовать больший индекс (больше столбцов), возможно, в дополнение к memcached, как упоминает @jcm. Часто индексы с одним столбцом не помогают, потому что они не используются вашими запросами. - person Seth; 12.01.2010

Распространенным подходом к решению проблем такого типа является сегментирование. К сожалению, реализовать это в основном зависит от ORM (Hibernate делает это прекрасно), и Django не поддерживает это. Однако я не уверен, что 4 миллиона строк — это действительно так уж плохо. Ваши запросы по-прежнему должны быть полностью управляемыми.

Возможно, вам следует изучить кэширование с помощью чего-то вроде memcached. Django поддерживает это достаточно хорошо.

person Jim Mitchener    schedule 12.01.2010

Вы не указали, какую базу данных вы используете. Некоторые базы данных, такие как MySQL и PostgreSQL, изначально имеют крайне консервативные настройки, которые практически неприменимы ни для чего, кроме крошечных баз данных на крошечных серверах.

Если вы сообщите нам, какую базу данных вы используете и на каком оборудовании она работает, а также используется ли это оборудование совместно с другими приложениями (например, обслуживает ли оно также веб-приложение), мы можем предоставить вам некоторые конкретные настройки. совет.

Например, с MySQL вам, вероятно, потребуется настроить параметры InnoDB; для PostgreSQL вам потребуется изменить shared_buffers и ряд других параметров.

person Dan Fairs    schedule 05.03.2012