Balancer Опубликовано 6 Августа 2004 Жалоба Поделиться Опубликовано 6 Августа 2004 Созрел я, наконец, до реализации давней идеи. Суть в том, чтобы постинги топиков, к которым давно не было обращений, сбрасывать в отдельную таблицу. А при обращении к ним - перекидывать их снова в основную. Решение оказалось даже несколько проще, чем я ожидал и серьёзно править в движке нужно только одно место одного файла Сразу предупреждаю, что готового решения не даю, ибо расписывать до буковки многое просто лень, тем, у кого форумы на сотни тысяч постингов, скорее всего, моих подсказок будет достаточно, а для других это решение бесполезно. Суть решения такая. Вводим учёт даты последнего чтения топика. Отдельным внешним скриптом скидываем то, к чему давно не было обращений в отдельную таблицу. В движке форума если при чтении из основной таблицы топики не были найдены, то пытаемся перебросить их из архивной в основную. Итак, по порядку. 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 Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Balancer Опубликовано 6 Августа 2004 Автор Жалоба Поделиться Опубликовано 6 Августа 2004 Закончен перенос постингов в архивную БД.Навскидку - всё работает.Внешне, кроме заметного ускорения работы и небольшой подтормозки при обращении к старому топику, разницы не видно Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Total Опубликовано 6 Августа 2004 Жалоба Поделиться Опубликовано 6 Августа 2004 а в чем приемущества ?? Ведь поиск в любом случае идет по обоим таблицам ? верно ? т.е. в чем экономия? Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Balancer Опубликовано 7 Августа 2004 Автор Жалоба Поделиться Опубликовано 7 Августа 2004 Полнотекстовый поиск - только по активной таблице. Т.е. в моём варианте - за последний месяц. Надо больше - используйте "внешний" поисковик или поиск по заголовкам. В любом случае использовать полный поиск за всё время, скажем, на моём форуме - это от десятков секунд до многих минут полного зависа форума. А FULLTEXT-index'ы в MySQL до сих пор слишком глючат на больших таблицах. Да и не сильно ускоряют они работу. Преимущество в том, что, в моём случае на всех обычных операциях нужно ворочать не 600Мб таблицей, а всего 200Мб, из-за чего сервер перестаёт "уходить в себя" на количестве народа в 200 чел. в онлайне. Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Balancer Опубликовано 7 Августа 2004 Автор Жалоба Поделиться Опубликовано 7 Августа 2004 Чтобы поисковые боты не поднимали топики из архива, нужно следующим образом модифицировать 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(); } Заодно поисковые боты не будут накручивать счётчики просмотра. Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Total Опубликовано 7 Августа 2004 Жалоба Поделиться Опубликовано 7 Августа 2004 Balancer а дай линку на свой форум -- чтобы посмотреть, можно в приват, если огласка не нужна Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Iris Опубликовано 7 Августа 2004 Жалоба Поделиться Опубликовано 7 Августа 2004 Total http://forums.airbase.ru/index.php?showtopic=28960 Цитата Ссылка на комментарий Поделиться на других сайтах Прочее
Рекомендуемые сообщения
Присоединиться к обсуждению
Вы можете ответить сейчас, а зарегистрироваться позже. Если у вас уже есть аккаунт, войдите, чтобы ответить от своего имени.