Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Ускорит ли разбиение одного запроса на несколько загрузку страницы?
 
 автор: TetRiska   (13.07.2011 в 14:54)   письмо автору
 
 

Всем привет. Вот хотел бы спросить знающих про еще большее ускорение запроса. Вопрос продолжающий прошлую тему, но уже с исправлениями ошибок. Имею такой код:
$sql5 = "
        SELECT `em_produce_id`
        FROM `em_produce` a 
        JOIN `em_company` f ON (f.`em_company_id` = a.`em_company_id` AND f.`em_company_access` = 'y' AND f.`em_company_deleted` = 'n')    
        WHERE a.`em_produce_direct` = ".$res['result']['em_category_id'][0]."
        AND a.`em_produce_access` = 'y'
        AND a.`em_produce_deleted` = 'n'
        ";
        
$res5 = select_query($sql5); //запросом этим я получаю количество записей для дальнейшего отбора через лимит и построения пагинатора

$goods    = '';
$navigate = '';

if($res5['count'] != 0){
    $page     = isset($_GET['page']) && $_GET['page'] > 0 ? intval($_GET['page']) : 1;
    $per_page = 10;
    $path     = 'dir/'.$dir;
    $total    = (($res5['count'] - 1) / $per_page) + 1;
    $total    =  intval($total);
    if($page > $total) $page = $total;
    
    $from = ($page-1)*$per_page;
    $to   = $page*$per_page;
    $to   = ($to > $res5['count']) ? $res5['count'] : $to;

    $sql6 = "
            SELECT a.`em_produce_name`,
                   a.`em_produce_desc_short`,
                   a.`em_produce_price_ua`,
                   a.`em_produce_price_us`,
                   a.`em_produce_price_eu`,
                   a.`em_produce_image_sm`,
                   a.`em_produce_year`,
                   a.`em_produce_distance`,
                   a.`em_produce_motohours`,
                   a.`em_produce_flyhours`,
                   a.`em_produce_valume`,
                   a.`em_produce_country`,
                   a.`em_produce_color`,
                   a.`em_produce_maxspeed`,
                   a.`em_produce_fuelflou`,
                   a.`em_produce_tub`,
                   a.`em_produce_data_upd`,
                   a.`em_element_id`,
                   a.`em_produce_url`, 
                   a.`em_produce_subcategory` as pp_category_id,
                   b.`em_category_name` as pp_category_name,
                   a.`em_produce_group` as pp_rubrik_id,
                   c.`em_category_name` as pp_rubrik_name,
                   a.`em_brand_id` as pp_brand_id,
                   d.`em_brand_name` as pp_brand_name,
                   f.`em_city_id` as pp_city_id,
                   p.`em_city_name` as pp_city_name,
                   e.`em_produce_stat_overal`,
                   f.`em_company_profile_url`,
                   f.`em_company_name`,
                   f.`em_company_plogo`,
                   g.`em_package_name`,
                   g.`em_package_type`
            FROM `em_produce` a 
            LEFT JOIN `em_category` b ON (b.`em_category_id` = a.`em_produce_subcategory` AND b.`em_category_access` = 'y' AND b.`em_category_deleted` = 'n')
            LEFT JOIN `em_category` c ON (c.`em_category_id` = a.`em_produce_group` AND c.`em_category_access` = 'y' AND c.`em_category_deleted` = 'n')
            LEFT JOIN `em_brand` d ON (d.`em_brand_id` = a.`em_brand_id` AND d.`em_brand_access` = 'y' AND d.`em_brand_deleted` = 'n')
            LEFT JOIN `em_produce_stat` e ON (e.`em_produce_id` = a.`em_produce_id`)    
            JOIN `em_company` f ON (f.`em_company_id` = a.`em_company_id` AND f.`em_company_access` = 'y' AND f.`em_company_deleted` = 'n')    
            JOIN `em_package` g ON (g.`em_package_id` = f.`em_package_id`)
            LEFT JOIN `em_city` p ON (p.`em_city_id` = f.`em_city_id`)
            WHERE a.`em_produce_direct` = ".$res['result']['em_category_id'][0]."
            AND a.`em_produce_access` = 'y'
            AND a.`em_produce_deleted` = 'n'
            ORDER BY g.`em_package_weight` DESC, e.`em_produce_stat_overal` DESC
            LIMIT ".$from.",".$to."
            ";
            
    $res6 = select_query($sql6);

    $f=0;
    for($g=0;$g<$res6['count'];$g++){
        $f++;
                                
        $goods .= strtr(file_get_contents(PATH_PATTERN . RUBRIC_GOODS_CONTENT_TPL), array(
            ...
        ));
    }
    $navigate = navigate($page, $total, $path);
}
$content_tpl = strtr(file_get_contents(PATH_PATTERN . CONTENT_TPL), array(
    '{GOODS}'            => $goods,
    '{NAVIGATE}'         => $navigate
));

Вот если со второго запроса вынести подключаемые таблицы и сделать отдельными запросами которые будут по циклу выполнятся, это будет хуже вариант или как? Хочется еще ускорить работу выборки+скрипта. Примерно так:
$sql6 = "
            SELECT a.`em_produce_name`,
                   a.`em_produce_desc_short`,
                   a.`em_produce_price_ua`,
                   a.`em_produce_price_us`,
                   a.`em_produce_price_eu`,
                   a.`em_produce_image_sm`,
                   a.`em_produce_year`,
                   a.`em_produce_distance`,
                   a.`em_produce_motohours`,
                   a.`em_produce_flyhours`,
                   a.`em_produce_valume`,
                   a.`em_produce_country`,
                   a.`em_produce_color`,
                   a.`em_produce_maxspeed`,
                   a.`em_produce_fuelflou`,
                   a.`em_produce_tub`,
                   a.`em_produce_data_upd`,
                   a.`em_element_id`,
                   a.`em_produce_url`, 
                   e.`em_produce_stat_overal`,
                   f.`em_company_profile_url`,
                   f.`em_company_name`,
                   f.`em_company_plogo`,
                   g.`em_package_name`,
                   g.`em_package_type`
            FROM `em_produce` a 
            LEFT JOIN `em_produce_stat` e ON (e.`em_produce_id` = a.`em_produce_id`)    
            JOIN `em_company` f ON (f.`em_company_id` = a.`em_company_id` AND f.`em_company_access` = 'y' AND f.`em_company_deleted` = 'n')    
            JOIN `em_package` g ON (g.`em_package_id` = f.`em_package_id`)
            WHERE a.`em_produce_direct` = ".$res['result']['em_category_id'][0]."
            AND a.`em_produce_access` = 'y'
            AND a.`em_produce_deleted` = 'n'
            ORDER BY g.`em_package_weight` DESC, e.`em_produce_stat_overal` DESC
            LIMIT ".$from.",".$to."
            ";
            
    $res6 = select_query($sql6);

for($c=0;$c<$res6['count'];$c++){
   $sql7 = "
            SELECT `em_category_name`
            FROM `em_category`
            WHERE `em_category_id` = ".$res5['result']['em_produce_subcategory'][$g]."
            ";
            
    $res7 = select_query($sql7);
}

и тд вынести остальные таблицы, не все, а лишь те 4, присоединение которых убрал из запроса $res6

  Ответить  
 
 автор: TetRiska   (13.07.2011 в 16:31)   письмо автору
 
   для: TetRiska   (13.07.2011 в 14:54)
 

что можете сказать по этому поводу?

  Ответить  
 
 автор: cheops   (13.07.2011 в 17:43)   письмо автору
 
   для: TetRiska   (13.07.2011 в 14:54)
 

Я боюсь при таком объеме нужно экспериментировать, аналитически тут уже сложно что-то сказать.

  Ответить  
 
 автор: TetRiska   (13.07.2011 в 17:56)   письмо автору
 
   для: cheops   (13.07.2011 в 17:43)
 

ясно, буду пробовать, но хотел бы еще спросить, вот у меня идет
ORDER BY g.`em_package_weight` DESC, e.`em_produce_stat_overal` DESC

без указания
e.`em_produce_stat_overal` DESC
запрос выполняется до 300 мс, а с ним почти секунду....поначалу я подумал, что это из за присоединения, так долго и тогда я создал такое же поле в главной таблице из которой идет основная выборка и получил такое
ORDER BY g.`em_package_weight` DESC, a.`em_produce_stat_overal` DESC

но результат остался таким же, почти секунда :( записей в таблице 26 000, вот я и думаю, что все из-за большого объема, обойти никак нельзя? но сортировка по em_produce_stat_overal мне очень нужна, как быть?

П.С. убрать из запроса
a.`em_produce_stat_overal` DESC
и потом на пхп произвести сортировку как по мне нельзя, т.к. неверно отсортирует - сортировать должно из всей выборки, а не из 0,10 по лимиту.

  Ответить  
 
 автор: cheops   (13.07.2011 в 18:03)   письмо автору
 
   для: TetRiska   (13.07.2011 в 17:56)
 

Какое значение у параметра/директивы sort_buffer_size? Скорее всего у вас промежуточная таблица на жесткий диск сбрасывается... Увеличение этого параметра может ускорить запрос.

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

  Ответить  
 
 автор: TetRiska   (13.07.2011 в 18:25)   письмо автору
 
   для: cheops   (13.07.2011 в 18:03)
 

это как я понял в пхп настраивается? и значение в мегабайтах?
а что за промежуточная таблица то? ведь em_produce_stat_overal находится в основной таблице

  Ответить  
 
 автор: cheops   (13.07.2011 в 18:31)   письмо автору
 
   для: TetRiska   (13.07.2011 в 18:25)
 

В my.ini. У вас многотабличный запрос, все эти объединения порождают промежуточные таблицы - если они убираются, они обрабатываются в оперативной памяти, если не убираются - сбрасываются на жесткий диск, где обработка идет медленнее.

  Ответить  
 
 автор: TetRiska   (13.07.2011 в 18:42)   письмо автору
 
   для: cheops   (13.07.2011 в 18:31)
 

т.е. без присоединения таблиц, запросы выполняются в оперативке и намного быстрей все это так? а если присоединяем, то увы жесткий диск гораздо медленней работает и поэтому дольше так?

  Ответить  
 
 автор: cheops   (13.07.2011 в 19:00)   письмо автору
 
   для: TetRiska   (13.07.2011 в 18:42)
 

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

  Ответить  
 
 автор: TetRiska   (13.07.2011 в 19:10)   письмо автору
 
   для: cheops   (13.07.2011 в 19:00)
 

а не могли бы Вы посмотреть дампы таблиц дампы и самый первый блок пхп кода с запросом, все ли там верно по индексам?

  Ответить  
 
 автор: cheops   (13.07.2011 в 20:26)   письмо автору
 
   для: TetRiska   (13.07.2011 в 19:10)
 

Там не с индексами проблема, а в то, что у вас таблица ненормализована, если это намерно - ОК, но такая неромализованная таблица, как правило, имеет большой объем, что может быть плохо, особенно в случае многотабличных запросов (как правило, ненормализованные таблицы держат только для однотабличных запросов и ни для чего более). Индексов для такого количества столбцов можно вводить много и самых разнообразных.

Когда такой объем данных, поступают вообще очень жестко, вводят таблицу из двух столбцов, которую обвешивают кучей других таблиц, в которых хранят все остальные данны
  `em_produce_id` int(10) unsigned NOT NULL auto_increment,
  `em_produce_parent` int(10) unsigned NOT NULL default '0',

Эта хребтовая таблица - будет очень маленькой и по ней будет осуществляться поиск очень быстро, через неё будет удобно связывать другие таблицы. А еще если товар добавляется не часто, то и вообще эту таблицу забрасывают в оперативную память (таблица типа MEMORY). Индексы - это хорошо, но это не единственный и не всегда самый эффективный вариант оптимизации базы данных

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования