Как упростить массив

vitek_gagra

Создатель
Регистрация
7 Янв 2009
Сообщения
47
Реакции
12
Здравствуйте уважаемые форумчане.
Подскажите как упростить массив, а то он сильно грузит сервер
PHP:
while ($b = query_rw ("SELECT SQL_CALC_FOUND_ROWS n.*, c.`type_name` AS `cat_name`, COUNT(o.`hid`) AS `count_c` FROM (`newss` AS n, `art_parts` AS c) LEFT JOIN `news_comments` AS o ON (o.`hid` = n.`news_id`) WHERE c.`active` = 1 AND c.`type_id` = ".$_idc." AND n.`active` = 1 AND n.`part_id` = ".$_idc." GROUP BY n.`news_id` ORDER BY n.`news_date` DESC LIMIT ".$_offset.', '.$_limit)) {
            if (strval ($b['reviews']) == '') $b['reviews'] = 0;
           
            preg_match ('|^(\d{4})\-(\d{2})\-(\d{2})$|', $b['news_date'], $o);
            if (isset ($o[1]) && isset ($o[2]) && isset ($o[3])) $b['news_date'] = mktime (5, 0, 0, $o[2], $o[3], $o[1]); else $b['news_date'] = time ();
           
            if ($b['img'] == '') $b['img'] = 'http://'.SITE_HOST.'/images/v2/nopic.jpg'; else $b['img'] = 'http://'.SITE_HOST.'/news_pics/'.$b['img'];
           
            $a[] = array (
                'name' => $b['news_head'],
                'text' => $b['news_anons'],
                'date' => $b['news_date'],
                'image' => $b['img'],
                'url' => 'http://'.SITE_HOST.'/news/'.$_idc.'/'.$b['news_id'].'/',
                'count_c' => $b['count_c'],
                'count_v' => $b['reviews']
            );
           
            if (!isset ($_cname)) $_cname = $b['cat_name'];
        }

Этот массив делает выборку новостей из разделов в таблице art_parts выводит, на страницу раздела новостей список новостей из newss разбивает на страници и показывает сколько комментов (news_comments) у каждой новости.
Движок самописный, программист кто писал движок отказывается переделывать говорит больше не занимается клиентскими сайтами и говорит что все хорошо написано, но у меня vps ложится, особенно когда показывается раздел архива новостей (1112 новостей).
Я в этом не особо разбираюсь. Подскажите пожалуйста как его облегчить?!
 
честно говоря вообще непонятно зачем здесь цикл.. здесь можно сделать все одной выборкой вместо того чтобы делать кучу запросов в цикле (как я понял идет получение по одной новости), это думаю уже значительно облегчит работу скрипта
дальше можно с легкостью избавиться от left join'a - сделать отдельный один запрос и мержить данные на php
 
Хотелось бы глянуть на файл работы с БД и в частности на функцию query_rw.
На первый взгляд, код ощущается как бесконечный цикл, а с таким и самый мощный дедик не справится :)

Чтобы оптимизировать запрос надо знать структуру таблиц - правильно расставленные индексы в десятки раз могут ускорить выполнение.

дальше можно с легкостью избавиться от left join'a - сделать отдельный один запрос и мержить данные на php

Join сам по себе ничем не плох и если правильно применяется, то отработает быстрее нескольких запросов и обработки php-скриптом.
 
Добавил файловое кеширование и немного переписал запрос

PHP:
//Простое файловое кеширование - начало
       
        $filename = 'cache/cache_' . $_idc . '_' . $_offset . '_' . $_limit;
       
        if (is_file($filename) and filemtime($filename) > (time() - 3600)) {
           
            $array = unserialize(file_get_contents($filename));
       
            $a = $array['a'];
           
            $b = $array['b'];
           
            $_cname = $array['_cname'];
       
            $num_rows = $array['_num_rows'];
       
        }
       
        if (!$array) {
            $query = mysql_query("select * from newss where active=1 and part_id=".$_idc." order by news_date desc;");
            $num_rows = (int)mysql_num_rows($query);
            while ($b = query_rw ("SELECT * FROM (`newss` AS n, `art_parts` AS c) WHERE c.`active` = 1 AND c.`type_id` = ".$_idc." AND n.`active` = 1 AND n.`part_id` = ".$_idc." GROUP BY n.`news_id` ORDER BY n.`news_date` DESC LIMIT ".$_offset.', '.$_limit)) {
           
            $query = mysql_query("select type_name from art_parts where active=1 and type_id=".$_idc.";");
            $res = mysql_fetch_array($query);
           
                if (strval ($b['reviews']) == '') $b['reviews'] = 0;
               
                preg_match ('|^(\d{4})\-(\d{2})\-(\d{2})$|', $b['news_date'], $o);
                if (isset ($o[1]) && isset ($o[2]) && isset ($o[3])) $b['news_date'] = mktime (5, 0, 0, $o[2], $o[3], $o[1]); else $b['news_date'] = time ();
               
                if ($b['img'] == '') $b['img'] = 'http://'.SITE_HOST.'/images/v2/nopic.jpg'; else $b['img'] = 'http://'.SITE_HOST.'/news_pics/'.$b['img'];
               
                $a[] = array (
                    'name' => $b['news_head'],
                    'text' => $b['news_anons'],
                    'date' => $b['news_date'],
                    'image' => $b['img'],
                    'url' => 'http://'.SITE_HOST.'/news/'.$_idc.'/'.$b['news_id'].'/',
                    'count_c' => $b['count_c'],
                    'count_v' => $b['reviews']
                );
               
                if (!isset ($_cname)) $_cname = $res['type_name'];
            }
           
            file_put_contents($filename, serialize(array('a' => $a, 'b' => $b, '_cname' => $_cname, '_num_rows' => $num_rows)));       
           
        }
 
        //Простое файловое кеширование - конец
       
        if (count ($a) > 0) {
 
            $_count = (int) $_res[0];
            $_pages = ceil ($num_rows/$_limit);
           
            if ($_pages > 1) $_data['loop']['navi'] = prepare_navigation ($_pages, $_page, $_data['url_clear']);
        }
Не знаю правильно или нет, но работает :) Стал гораздо быстрее работать сайт и не грузит сервер.
Осталось сделать подсчет комментариев. Вот это не знаю как правильно сделать.
Вот таблица комментариев к новостям. в hid указывается id новости

Код:
CREATE TABLE IF NOT EXISTS `news_comments` (
  `cid` int(10) unsigned NOT NULL auto_increment,
  `hid` int(11) unsigned default NULL,
  `aid` int(10) unsigned default NULL,
  `tblname` varchar(250) character set utf8 default NULL,
  `usr_login` varchar(250) character set utf8 default NULL,
  `usr_mail` varchar(250) character set utf8 default NULL,
  `usr_mess` text character set utf8,
  `likenotlike` int(10) default '0',
  `alllikenotlike` int(10) default '0',
  `add_date` datetime default NULL,
  `checked` int(10) unsigned default NULL,
  `active` int(1) unsigned default NULL,
  `ip` bigint(20) unsigned NOT NULL,
  PRIMARY KEY  (`cid`)
)

Вот таблица новостей. news_id это id новости, part_id это id раздела новостей.

Код:
CREATE TABLE IF NOT EXISTS `newss` (
  `news_id` int(11) unsigned NOT NULL auto_increment,
  `part_id` int(10) unsigned default NULL,
  `news_head` varchar(200) default NULL,
  `news_anons` text,
  `news_mess` text,
  `news_descr` varchar(200) default NULL,
  `news_keys` varchar(200) default NULL,
  `news_date` date default NULL,
  `img` varchar(250) default NULL,
  `aslink` int(1) unsigned default NULL,
  `active` int(1) unsigned default NULL,
  `comment` int(1) unsigned NOT NULL default '1',
  `reviews` int(11) unsigned default NULL,
  `autor` varchar(30) NOT NULL default 'Admin',
  `isto4nik` varchar(250) NOT NULL,
  `isto4nik_name` varchar(30) NOT NULL,
  PRIMARY KEY  (`news_id`)
)

А вот таблица разделов новостей. type_id это id раздела новостей

Код:
CREATE TABLE IF NOT EXISTS `art_parts` (
  `type_id` int(10) unsigned NOT NULL auto_increment,
  `type_name` varchar(250) character set cp1251 default NULL,
  `order_num` int(10) default NULL,
  `active` int(1) unsigned default NULL,
  `gl` int(1) unsigned NOT NULL default '0',
  PRIMARY KEY  (`type_id`)
)

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