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

 
+
-
edit
 

Balancer

администратор
★★★★☆

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

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

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

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

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

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

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

2. Делаем альтернативную таблицу в БД форума. Внимание, все префиксы у меня не ib_, а ib_! Так что меняйте сами!
code mysql
  1. CREATE TABLE `ib_posts_archive` (
  2.   `append_edit` tinyint(1) default '0',
  3.   `edit_time` int(10) default NULL,
  4.   `pid` int(10) NOT NULL auto_increment,
  5.   `ubb_topic` varchar(11) default NULL,
  6.   `ubb_post` int(11) default '0',
  7.   `post` text NOT NULL,
  8.   `author_id` mediumint(8) NOT NULL default '0',
  9.   `author_name` varchar(32) default NULL,
  10.   `use_sig` tinyint(1) NOT NULL default '0',
  11.   `use_emo` tinyint(1) NOT NULL default '0',
  12.   `ip_address` varchar(16) NOT NULL default '',
  13.   `post_date` int(10) NOT NULL default '0',
  14.   `icon_id` smallint(3) default NULL,
  15.   `queued` tinyint(1) NOT NULL default '0',
  16.   `topic_id` int(10) NOT NULL default '0',
  17.   `post_title` varchar(255) default NULL,
  18.   `new_topic` tinyint(1) default '0',
  19.   `edit_name` varchar(255) default NULL,
  20.   `post_type` varchar(4) default NULL,
  21.   `post_parent` int(10) NOT NULL default '0',
  22.   `post_key` varchar(32) NOT NULL default '0',
  23.   `post_htmlstate` smallint(1) NOT NULL default '0',
  24.   PRIMARY KEY  (`pid`),
  25.   KEY `pid` (`pid`)
  26. );


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

3. Ищем по файлам строки типа
code text
  1.     'set'    => 'views=views+1',


и меняем на
code text
  1.     'set'    => 'views=views+1, last_view_date='.time(),


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

Можно также (полезно, но не обязательно) найти все строки с
code text
  1. 'views'            => 0,

и приписать после них
code text
  1. 'last_view_date'   => time(),

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

Теперь - главное. Лезем в ips_kernel\class_db_mysql.php
Ищем функцию
function query($the_query, $bypass=0) {

Находим запрос:
code text
  1.         $this->query_id = mysql_query($the_query, $this->connection_id);


После него дописываем:
code text
  1.         if(preg_match("!ib_posts!",$the_query))
  2.         {
  3.             if(!mysql_num_rows($this->query_id))
  4.             {
  5.                 if(preg_match("!topic_id=(\d+)!",$the_query,$bal_t_m))
  6.                 {
  7.                     $bal_t_fh=fopen("from_archive_move.log","at");
  8.                     fwrite($bal_t_fh, strftime("%d.%m.%Y %H:%M:%S")."|$the_query\n");
  9.                     fclose($bal_t_fh);
  10.  
  11.                     $bal_t_q = "REPLACE `ib_posts` SELECT * FROM `ib_posts_archive` WHERE `topic_id`={$bal_t_m[1]}";
  12.                     if(!mysql_query($bal_t_q, $this->connection_id))
  13.                         $this->fatal_error("mySQL query error: $bal_t_q");
  14.  
  15.                     $bal_t_q = "DELETE FROM `ib_posts_archive` WHERE `topic_id`={$bal_t_m[1]}";
  16.                     if(!mysql_query($bal_t_q, $this->connection_id))
  17.                         $this->fatal_error("mySQL query error: $bal_t_q");
  18.  
  19.                     $this->query_id = mysql_query($the_query, $this->connection_id);
  20.                 }
  21.             }
  22.         }


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

Осталось только привести скрипт по архивации постингов:
code php
  1. #!/usr/local/bin/php
  2. <font size=1><xmp>
  3. <?
  4.  
  5. ini_set('default_charset','utf-8');
  6. setlocale(LC_ALL, "ru_RU.utf8");
  7.  
  8. $dbh = @mysql_connect("localhost", "<user>", "<password>") or die ("Could not connect");
  9. @mysql_select_db("FORUM") or die ("Could not select database");
  10.  
  11. $q="SELECT `tid` FROM `ib_topics` WHERE `posts`<>0 AND `last_post`<".(time()-30*86400)." AND `last_view_date`<".(time()-30*86400);
  12. $res = mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");
  13.  
  14. $n=0;
  15. $s=0;
  16.  
  17. while($row = mysql_fetch_array($res))
  18. {
  19.     $q="REPLACE `ib_posts_archive` SELECT * FROM `ib_posts` WHERE `topic_id`={$row['tid']}";
  20.     mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");
  21.     $r = mysql_affected_rows();
  22.  
  23.     $q="DELETE FROM `ib_posts` WHERE `topic_id`={$row['tid']}";
  24.     mysql_query ($q) or  die ("Query '$q' failed, error ".mysql_errno().": ".mysql_error()."<BR>");
  25.     if($r)
  26.         $n++;
  27.  
  28.     $s+=$r;
  29. }
  30.  
  31. echo "$n topics / $s posts was moved";
  32.  
  33. ?></xmp></font>


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

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

Balancer

администратор
★★★★☆

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

code text
  1.         //-------------------------------------
  2.         // Update the topic views counter
  3.         //-------------------------------------
  4.  
  5.         if(!$ibforums->is_bot)
  6.         {
  7.             $DB->simple_construct( array( 'update' => 'topics',
  8.                                           'set'    => 'views=views+1, last_view_date='.time(),
  9.                                           'where'  => "tid=".$this->topic['tid'],
  10.                                 )      );
  11.                            
  12.             $DB->simple_shutdown_exec();
  13.         }


Заодно поисковые боты не будут накручивать счётчики просмотра.
 
RU Наблюдатель #08.08.2004 09:11
+
-
edit
 

Наблюдатель

новичок
Прелестно! Возникли вопросы:

1. Это ускоряет работу движка - разгружает ресурсы базы? (т.е. "а нафига?") Или просто разгружает модераторов?
2. Где находится Архив? Что это - подфорум или отдельный форум, или Отстойник? Или это вообще исчезает из поля зрения, но доступно по поиску?
 
RU Balancer #08.08.2004 11:09  @Наблюдатель#08.08.2004 09:11
+
-
edit
 

Balancer

администратор
★★★★☆

Наблюдатель>1. Это ускоряет работу движка - разгружает ресурсы базы? (т.е. "а нафига?") Или просто разгружает модераторов?

Конечно - движка. Для пользователей (и модераторов, администраторов) остаётся всё прозрачно.

Наблюдатель>2. Где находится Архив? Что это - подфорум или отдельный форум, или Отстойник? Или это вообще исчезает из поля зрения, но доступно по поиску?[»]

Это отдельная таблица в БД.
И, как я писал выше (читай внимательнее) для поиска по тексту недоступно. Только по заголовкам. А полнотекстовый поиск - или внешними утилитами или за фиксированный период времени.
 

в начало страницы | новое
 
Поиск
Поддержка
Поддержи форум!
ЯндексЯндекс. ДеньгиХочу такую же кнопку
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru