Перейти к контенту

Архив постингов в отдельной таблице


Balancer

Рекомендуемые сообщения

Созрел я, наконец, до реализации давней идеи. Суть в том, чтобы постинги топиков, к которым давно не было обращений, сбрасывать в отдельную таблицу. А при обращении к ним - перекидывать их снова в основную.

 

Решение оказалось даже несколько проще, чем я ожидал и серьёзно править в движке нужно только одно место одного файла :D

 

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

 

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

 

Итак, по порядку.

 

0. Делаем бэкап базы. На всякий пожарный.

 

1. Добавляем к таблице ibf_topics новое поле `last_view_date` типа INT.

 

2. Делаем альтернативную таблицу в БД форума. Внимание, все префиксы у меня не ibf_, а ib_! Так что меняйте сами!

CREATE TABLE `ib_posts_archive` (
 `append_edit` tinyint(1) default '0',
 `edit_time` int(10) default NULL,
 `pid` int(10) NOT NULL auto_increment,
 `ubb_topic` varchar(11) default NULL,
 `ubb_post` int(11) default '0',
 `post` text NOT NULL,
 `author_id` mediumint(8) NOT NULL default '0',
 `author_name` varchar(32) default NULL,
 `use_sig` tinyint(1) NOT NULL default '0',
 `use_emo` tinyint(1) NOT NULL default '0',
 `ip_address` varchar(16) NOT NULL default '',
 `post_date` int(10) NOT NULL default '0',
 `icon_id` smallint(3) default NULL,
 `queued` tinyint(1) NOT NULL default '0',
 `topic_id` int(10) NOT NULL default '0',
 `post_title` varchar(255) default NULL,
 `new_topic` tinyint(1) default '0',
 `edit_name` varchar(255) default NULL,
 `post_type` varchar(4) default NULL,
 `post_parent` int(10) NOT NULL default '0',
 `post_key` varchar(32) NOT NULL default '0',
 `post_htmlstate` smallint(1) NOT NULL default '0',
 PRIMARY KEY  (`pid`),
 KEY `pid` (`pid`)
);

 

Таблица - фактически копия ib_posts, только выкинуты ненужные индексы.

 

3. Ищем по файлам строки типа

    'set'    => 'views=views+1',

 

и меняем на

    'set'    => 'views=views+1, last_view_date='.time(),

 

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

 

Можно также (полезно, но не обязательно) найти все строки с

'views'            => 0,

и приписать после них

'last_view_date'   => time(),

это мы впишем дату для создаваемых вновь топиков.

 

Теперь - главное. Лезем в ips_kernel\class_db_mysql.php

Ищем функцию

function query($the_query, $bypass=0) {

 

Находим запрос:

       $this->query_id = mysql_query($the_query, $this->connection_id);

 

После него дописываем:

       if(preg_match("!ib_posts!",$the_query))
       {
           if(!mysql_num_rows($this->query_id))
           {
               if(preg_match("!topic_id=(\d+)!",$the_query,$bal_t_m))
               {
                   $bal_t_fh=fopen("from_archive_move.log","at");
                   fwrite($bal_t_fh, strftime("%d.%m.%Y %H:%M:%S")."|$the_query\n");
                   fclose($bal_t_fh);

                   $bal_t_q = "REPLACE `ib_posts` SELECT * FROM `ib_posts_archive` WHERE `topic_id`={$bal_t_m[1]}";
                   if(!mysql_query($bal_t_q, $this->connection_id))
                       $this->fatal_error("mySQL query error: $bal_t_q");

                   $bal_t_q = "DELETE FROM `ib_posts_archive` WHERE `topic_id`={$bal_t_m[1]}";
                   if(!mysql_query($bal_t_q, $this->connection_id))
                       $this->fatal_error("mySQL query error: $bal_t_q");

                   $this->query_id = mysql_query($the_query, $this->connection_id);
               }
           }
       }

 

Всё. Должно работать.

 

Осталось только привести скрипт по архивации постингов:

#!/usr/local/bin/php
<font size=1><xmp>
<?

ini_set('default_charset','utf-8');
setlocale(LC_ALL, "ru_RU.utf8");

$dbh = @mysql_connect("localhost", "<user>", "<password>") or die ("Could not connect");
@mysql_select_db("FORUM") or die ("Could not select database");

$q="SELECT `tid` FROM `ib_topics` WHERE `posts`<>0 AND `last_post`<".(time()-30*86400)." AND `last_view_date`<".(time()-30*86400);
$res = mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");

$n=0;
$s=0;

while($row = mysql_fetch_array($res))
{
   $q="REPLACE `ib_posts_archive` SELECT * FROM `ib_posts` WHERE `topic_id`={$row['tid']}";
   mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");
   $r = mysql_affected_rows();

   $q="DELETE FROM `ib_posts` WHERE `topic_id`={$row['tid']}";
   mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");
   if($r)
       $n++;

   $s+=$r;
}

echo "$n topics / $s posts was moved";

?></xmp></font>

 

И запускаем этот скрипт, скажем, раз в сутки по CRON'у. Он перебросит все сообщения, к которым не было обращений больше месяца и последний ответ которых старше, чем в 1 месяц в архив.

 

Да, ещё замечу, что решение это только что реализованное. Возможны какие-то ошибки ;) Но, во-первых, мы сделали бэкап, а во-вторых, ничего страшного быть тут не должно :)

Добавлено в [mergetime]1091812587[/mergetime]

Блин, админы форума, ну настройте вы корректное отображение CODE-блоков! Экранировка откуда-то вылезла. В общем, листинги отсюда не берите, берите с http://forums.airbase.ru/index.php?showtopic=28960

Ссылка на комментарий
Поделиться на других сайтах

Закончен перенос постингов в архивную БД.

Навскидку - всё работает.

Внешне, кроме заметного ускорения работы и небольшой подтормозки при обращении к старому топику, разницы не видно :D

Ссылка на комментарий
Поделиться на других сайтах

а в чем приемущества ?? Ведь поиск в любом случае идет по обоим таблицам ? верно ? т.е. в чем экономия?
Ссылка на комментарий
Поделиться на других сайтах

Полнотекстовый поиск - только по активной таблице. Т.е. в моём варианте - за последний месяц. Надо больше - используйте "внешний" поисковик или поиск по заголовкам. В любом случае использовать полный поиск за всё время, скажем, на моём форуме - это от десятков секунд до многих минут полного зависа форума. А FULLTEXT-index'ы в MySQL до сих пор слишком глючат на больших таблицах. Да и не сильно ускоряют они работу.

 

Преимущество в том, что, в моём случае на всех обычных операциях нужно ворочать не 600Мб таблицей, а всего 200Мб, из-за чего сервер перестаёт "уходить в себя" на количестве народа в 200 чел. в онлайне.

Ссылка на комментарий
Поделиться на других сайтах

Чтобы поисковые боты не поднимали топики из архива, нужно следующим образом модифицировать sources/topics.php

 

       //-------------------------------------
       // Update the topic views counter
       //-------------------------------------

       if(!$ibforums->is_bot)
       {
           $DB->simple_construct( array( 'update' => 'topics',
                                         'set'    => 'views=views+1, last_view_date='.time(),
                                         'where'  => "tid=".$this->topic['tid'],
                               )      );

           $DB->simple_shutdown_exec();
       }

 

Заодно поисковые боты не будут накручивать счётчики просмотра.

Ссылка на комментарий
Поделиться на других сайтах

Balancer а дай линку на свой форум -- чтобы посмотреть, можно в приват, если огласка не нужна
Ссылка на комментарий
Поделиться на других сайтах

Ссылка на комментарий
Поделиться на других сайтах

Присоединиться к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вы вставили отформатированный текст.   Удалить форматирование

  Допустимо не более 75 смайлов.

×   Ваша ссылка была автоматически заменена на медиа-контент.   Отображать как ссылку

×   Ваши публикации восстановлены.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Зарузка...
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, вы соглашаетесь на использование файлов cookie, а также с нашим положением о конфиденциальности Политика конфиденциальности и пользовательским соглашением Условия использования.