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

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


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 а дай линку на свой форум -- чтобы посмотреть, можно в приват, если огласка не нужна
Ссылка на комментарий
Поделиться на других сайтах

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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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

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

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