SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 14.01.2013 12:12:50

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Оптимизация БД форума.

Нужны практические советы по оптимизации структцры БД форума.
Уже несколько раз обращался за советом к форумчанам и всегда получал обстоятельные и точные ответы.
Поэтому обращаюсь еще раз, возможно советы из этой темы пригодятся кому-то еще.
-------------------------------------------------------
В бд форума есть основные таблицы:
1. USERS:  id_user, username, passw, count_post.
2. POSTS:  id_post, id_topic, id_poster, name_poster, date_time_post, post_text.
3. TOPICS:  id_topic, id_razdel, title_lopic, id_author, name_author, last_post_id,  last_poster_id, last_poster_name, date_time_last_post, count_posts.
4. RAZDEL:  id_razdel, title_razdel.

Заранее хочу оптимизировать структуру БД под довольно большую нагрузку: 5-8 млн. сообщений, 300-500 тыс. тем, 30-50 тыс. хостов в день и около 200-300 тыс. просмотров в день. В онлайне постоянно 300-800 человек.
-------------------------------------------------------
1 глобальный ВОПРОС
При добавлении юзером сообщения оно добавляется в таблицу POSTS, одновременно в таблице USERS обновляется поле count_post, а так же в таблице TOPICS обновляются поля: last_post_id,  last_poster_id, last_poster_name, date_time_last_post, count_posts.

Мне нужно сделать запрос на формирование  главной страницы форума (например как на форуме sqlinfo.ru).
То есть нужно вытащить название раздела, количество тем и сообщений в разделе, автора и время последнего поста в разделе.
Сначала планировал сделать так:
1. Первым запросом запрашиваю из таблицы RAZDEL название разделов.
2. Из TOPICS  запрашиваю все поля для тем, сгруппировав по разделам и найдя для каждого раздела тему с максимальным  last_post_id.
То есть у меня будет для каждого раздела вытянуты параметры темы в которой написано последнее сообщение в разделе:
SELECT t1.id_topic, t1.title_topic, t1.id_author, t1.name_author, t1.last_post_id, t1.last_poster_id, t1.last_poster_name, t1.date_time_last_post
FROM TOPICS t1
WHERE t1.last_post_id = ( SELECT t2.last_post_id
                                                FROM TOPICS t2
                                      WHERE t2.id_razdel = t1.id_razdel
                                                ORDER BY t2.last_post_id DESC LIMIT 1 )
ORDER BY t1.last_post_id DESC;
3. Третьим запросом вытаскиваю с помощью GROUP BY количество тем и постов для каждого раздела.

Теперь появилась идея в таблицу RAZDEL добавить поля: last_post_id,  last_poster_id, last_poster_name, date_time_last_post, count_posts, count_topics.
Терерь при добавлении юзером сообщения, оно добавляется в таблицу POSTS, одновременно в таблице USERS обновляется поле count_post, в таблице TOPICS обновляются поля: last_post_id,  last_poster_id, last_poster_name, date_time_last_post, count_posts,
в таблице RAZDEL обновляются поля: last_post_id,  last_poster_id, last_poster_name, date_time_last_post, count_posts. И при создании темы обновляется count_topics.

Теперь одним простым запросом можно сформировать главную страницу.

Что с точки зрения оптимальности лучше сделать: первый вариант или второй (догадываюсь, что второй).
Но вот не слишком ли много АПДЕЙТОВ в 3-х таблицах при добавлении одного поста при довольно частом постинге? Не будет ли при многочисленных апдейтах тормозить сервер в моём случае при такой нагрузке?

Отредактированно new_saler (14.01.2013 12:21:29)

Неактивен

 

#2 14.01.2013 12:21:58

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Оптимизация БД форума.

2 глобальный ВОПРОС
Это на счет хранения текста поста в таблице POSTS.
Как я уже писал: заранее хочу оптимизировать структуру БД под довольно большую нагрузку: 5-8 млн. сообщений, 300-500 тыс. тем, 30-50 тыс. хостов в день и около 200-300 тыс. просмотров в день. В онлайне постоянно 300-800 человек.

У данного поля post_text будет индекс FULLTEXT. Не лучше ли будет хранить текст постов в отдельной таблице, где будет id_post и post_text?

До этого в книге прочитал, что из-за наличия большого текстового поля в таблице и индекса FULLTEXT на нем может снижаться скорость доступа к таблице, а ведь при такой нагрузке из таблицы POSTS будут постоянно выбираться например 20 постов для формирования определённой страницы при просмотре темы.
А так же будут постоянно добавляться новые посты – не замедлит ли индекс FULLTEXT добавление данных (ведь, если я не ошибаюсь, при добавлении будет перестраиваться индекс для всей этой огромной таблицы.)

Не лучше ли будет выбрать id поста из таблицы POSTS а потом join-ом присоединить текст поста к данной выборке?

Неактивен

 

#3 16.01.2013 13:32:52

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Оптимизация БД форума.

Если сильно много написал, то хотя бы этот вопрос:

1. Не слишком ли много АПДЕЙТОВ в 3-х таблицах (users, posts, topics, razdel) при добавлении поста?

Получается, что много апдейтов, НО формирование главной страницы происходит за один простой запрос (так же как и страницы просмотра тем).

Отредактированно new_saler (16.01.2013 13:34:05)

Неактивен

 

#4 16.01.2013 21:52:21

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Оптимизация БД форума.

Возможно отвечу не совсем на заданные вопросы. Спросите еще, если что-то останется непонятным.

1. Заранее оптимизировать обычно нельзя (Преждевременная оптимизация - корень всех зол). В этом смысле избыточность информации за счет денормализации - то, что делается последним, после того как готова вся база. Чтобы оптимизировать скорость нужно иметь реалистичное представление о количестве тех или иных запросов (например см. открытую статистику liveinternet на sqlinfo, чтобы оценить отношение просмотров и постов).

2. Существуют реализации форумов, которые в той или иной степени решают проблему производительности. Среди таких могу отметить punbb (движок, используемый на sqlinfo) и vbulletin - платный, но не дорогой коммерческий движок. punbb лучше, так как его код предельно прозрачен. Можно установить такой движок, наполнить контентом и смоделировать его нагрузку. Это даст понимание о том, какие именно запросы являются узким местом системы. Именно на них нужно будет сконцентрировать оптимизационные усилия.

3. Обновлять 3 или 4 таблицы - разницы принципиальной нет (таблица razdel маленькая - ее апдейт будет быстрым). В случае сверходновременности, рекомендуется использовать движок Innodb, так как в нем будет существенно меньше блокировок при одновременных выборках и обновлениях. Innodb не поддерживает FULLTEXT-индексы, поэтому это является аргументом для использования отдельной таблицы для текстов сообщений в формате MyISAM. Остальные аргументы не являются значимыми - индекс при добавлении записи не перестраивается, а просто добавляются слова данной записи. Некоторое замедление при этом есть. vbulletin, например, предлагает выбрать - использовать fulltext-индексы или собственную индексирующую поисковую систему.

4. В punbb информация о последнем сообщении продублирована в таблице forums. Это важный аргумент в пользу того, чтобы так сделать.

CREATE TABLE `f_forums` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `forum_name` varchar(80) NOT NULL default 'New forum',
  `forum_desc` text,
  `redirect_url` varchar(100) default NULL,
  `moderators` text,
  `num_topics` mediumint(8) unsigned NOT NULL default '0',
  `num_posts` mediumint(8) unsigned NOT NULL default '0',
  `last_post` int(10) unsigned default NULL,
  `last_post_id` int(10) unsigned default NULL,
  `last_poster` varchar(200) default NULL,
  `sort_by` tinyint(1) NOT NULL default '0',
  `disp_position` int(10) NOT NULL default '0',
  `cat_id` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Неактивен

 

#5 21.01.2013 15:43:27

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Оптимизация БД форума.

rgbeast, прочитал, немного осмыслил.

Пока что у меня вырисовывается такая картина:

1. Таблицу USERS сделать типа InnoDB, на основании что при добавлени юзером поста в ней будет обновляться поле count_post. То есть в таблице будем много частых обновлений и одновременно чтений: при просмотре страницы определенного топика данные из таблицы users будут JOIN-иться к данным из таблицы постов.

2. Таблицу TOPICS сделать типа InnoDB на основании того что в ней будет много обновлений полей last_post_id,  last_poster_id и одновременно чтений при просмотре пользователями страницы раздела с топиками.

3. Таблицу POSTS сделать типа MyISAM потому что в ней будет мало обновлений и много вставок и чтений. Ведь MyISAM лучше чем InnoDB подходит для быстрого чтения.
Но тут же возникает вопрос: ведь столько же чтений будет из таблицы USERS (при просмотре страницы топика) а я таблицу USERS уже сделал типа InnoDB, так как в ней много обновлений... как с этм быть?

4. Текст сообщения не отделять отдельно, а поместить в таблицу POSTS вместе с остальными данными поста.
Так как прочитал, что MySQL хранит поля text и blob отдельно от остальных данных...
10.5. Data Type Storage Requirements: […] For BLOB and TEXT data, the information is stored internally in a different area of memory than the row buffer. […]
(Хотя так же встречал противоречивые мнения по этому поводу - люди расходятся во мнениях)
Основной запрос к таблице постов будет на формирование определённой страницы при просмотре топика.
Например хочу просмотреть 3-ю страницу (на странице выводится по 20 постов) топика с ID = 21:

SELECT * FROM posts WHERE id_topic = 21 ORDER BY id_post LIMIT 40, 20


Как будет вести себя MySQL в данном случае с полем post_text и вообще с запросом?...
У меня так же есть вопрос по поводу оптимальности этого запроса... ( не будет ли MySQL получать и сохранять в памяти например все 1000 постов для темы, а ПОТОМ уже выбирать нужные 20?

Отредактированно new_saler (21.01.2013 15:51:19)

Неактивен

 

#6 21.01.2013 15:59:44

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Оптимизация БД форума.

Для такого запроса индекс на id_post будет использован для сортировки, поэтому mysql выберет 60 записей, а потом отделит нужные 20. Если LIMIT будет для 100-ой страницы, например, то может иметь смысл заменить SELECT * на SELECT id_post, а потом уже вторым запросом выбрать нужные тексты.

Innodb не медленее, чем MyISAM на нагруженных проектах. Если posts будет в MyISAM, то в момент размещения нового сообщения все запросы будут ждать в очереди (а к таблице posts обращается большинство запросов на просмотр форума). Те цифры посещения, которые вы привели в первом посте подразумевают, что MyISAM может быть использован только как исключение и только для FULLTEXT-индекса.

Неактивен

 

#7 25.01.2013 16:58:16

new_saler
Участник
Зарегистрирован: 14.11.2012
Сообщений: 23

Re: Оптимизация БД форума.

Спасибо за ответы.

rgbeast написал:

Для такого запроса индекс на id_post будет использован для сортировки, поэтому mysql выберет 60 записей, а потом отделит нужные 20. Если LIMIT будет для 100-ой страницы, например, то может иметь смысл заменить SELECT * на SELECT id_post, а потом уже вторым запросом выбрать нужные тексты.

С этим вопросом разберусь позже - все протестирую и выберу оптимальный вариант.

rgbeast написал:

Innodb не медленее, чем MyISAM на нагруженных проектах. Если posts будет в MyISAM, то в момент размещения нового сообщения все запросы будут ждать в очереди (а к таблице posts обращается большинство запросов на просмотр форума). Те цифры посещения, которые вы привели в первом посте подразумевают, что MyISAM может быть использован только как исключение и только для FULLTEXT-индекса.

На счет цифр в первом посте это я погорячился…
Данные цифры возможны в довольно далекой перспективе - но я хотел заранее запроектировать БД на подобную нагрузку, чтобы максимально избежать модификаций в последующем.
В начале же реалии будут такие: размещение проекта на виртуальном хостинге до достижения некого порога посещаемости и нагрузки на сервер. (На первом этапе о VPS  со своими конфигами оборудования и речи идти не может.)
А начальная задача сводится к оптимальной и легкой работе приложения на вирт. хостинге.

Поэтому я задумался, не лучше ли будет для данного этапа все-таки использовать тип таблиц MyIsam...?
Так как прочитал про многие достоинства и недостатки InnoDB и MyISAM и думаю, что для виртуального хостинга на первом этапе существования проекта возможно движок InnoDB будет тяжеловат. Вот какие аргументы я встретил в сети:

....Innodb требует настройки ....... зачастую необходимо прикидывать расход оперативной памяти сервера (с MyISAM это будет в разы меньше, чем с InnoDB).

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

…..Дефолтные конфиги, кроме my-innodb-heavy-4G.cnf(ini), выделяют минимальный объём памяти под буфера InnoDB, позволяющие ему как-то функционировать, но, при сколько-нибудь значительном объёме данных в таблицах InnoDB, далеко не оптимально. Пока в ваших тестах на тысячу записей вы вряд ли столкнулись с этим моментом, но, для реального использования этого движка, конфиги надо будет подкорректировать….

Боюсь, что для вирт.  хостинга InnoBD будет тяжеловат, здесь смущает:
1. Расход оперативной памяти в разы ниже в MyISAM.
2. Дедлоки в InnoDB – не знаю что за зверь такой? Как с этим бороться?
3. Конфиги InnoDB на вирт. Сервере (минимальный объём памяти под буфера InnoDB). Повлиять на конфиги сервера на таком хостинге не получится.

Скажу, что это всё данные  2-4 летней давности. И возможно что-то изменилось? ,

Сейчас сделал анализ нескольких форумов:  уник. посетители, просмотры и кол-во постов в минуту:
1. 35 000 уник. 137 535 просмотров. 1 сообщение пишется в минуту. (570 тыс. сообщений в базе)
2. Посещаемость скрыта. 1,6 сообщений в минуту. (960 тыс. сообщений в базе)

Получается, если я не ошибаюсь, не очень много insert в таблицу posts и соответственно  update(в таблицах users, topics, razdel) : 1-2 апдейта всех таблиц в минуту и это уже на довольно посещаемых проектах.

Что скажете на счет типа движка под данную, начальную, задачу?
Потом со временем я так понимаю поменять тип движка очень просто.

Отредактированно new_saler (25.01.2013 16:59:32)

Неактивен

 

#8 25.01.2013 19:21:38

rgbeast
Администратор
MySQL Authorized Developer and DBA
Откуда: Москва
Зарегистрирован: 21.01.2007
Сообщений: 3880

Re: Оптимизация БД форума.

Это меняет постановку задачи. Одно дело как пробежать 100 км за сутки, а другое дело если речь идет про 2 км. То же самое с памятью - под изначальную задачу сразу представляется сервер с 128 гигами оперативки - понятно, что вопрос размера буферов по-умолчанию не стоит. Ряд вопросов очень сильно зависят от контекста - например "одеть ли шапку" имеет разный смысл в зависимости от того на улице 0 или -50.

Для VPS память будет существенна, так как конфигурации обычно ограничены по памяти и лишние 50 мегабайт на Innodb могут потребовать более высокого тарифа. В этом случае отключение InnoDB дает заметную экономию. В случае виртуального сервера круг возможностей обсуждать нагрузки очень узкий - нужно использовать тот движок, который удобнее хостеру (скорее всего MyISAM) и стараться не писать очень медленных запросов. Если будет реальная посещаемость, возникнет нагрузка на CPU (превышение разрешенного ресурса CPU) и хостер попросит перейти на VPS.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson