|
|
|
| Всем привет. Вот хотел бы спросить знающих про еще большее ускорение запроса. Вопрос продолжающий прошлую тему, но уже с исправлениями ошибок. Имею такой код:
$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 в 14:54)
| | что можете сказать по этому поводу? | |
|
|
|
|
|
|
|
для: TetRiska
(13.07.2011 в 14:54)
| | Я боюсь при таком объеме нужно экспериментировать, аналитически тут уже сложно что-то сказать. | |
|
|
|
|
|
|
|
для: 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 по лимиту. | |
|
|
|
|
|
|
|
для: TetRiska
(13.07.2011 в 17:56)
| | Какое значение у параметра/директивы sort_buffer_size? Скорее всего у вас промежуточная таблица на жесткий диск сбрасывается... Увеличение этого параметра может ускорить запрос.
PS Вообще факторов довольно много, особенно в многотабличном запросе, да промежуточная таблица может занимать значительный объем. | |
|
|
|
|
|
|
|
для: cheops
(13.07.2011 в 18:03)
| | это как я понял в пхп настраивается? и значение в мегабайтах?
а что за промежуточная таблица то? ведь em_produce_stat_overal находится в основной таблице | |
|
|
|
|
|
|
|
для: TetRiska
(13.07.2011 в 18:25)
| | В my.ini. У вас многотабличный запрос, все эти объединения порождают промежуточные таблицы - если они убираются, они обрабатываются в оперативной памяти, если не убираются - сбрасываются на жесткий диск, где обработка идет медленнее. | |
|
|
|
|
|
|
|
для: cheops
(13.07.2011 в 18:31)
| | т.е. без присоединения таблиц, запросы выполняются в оперативке и намного быстрей все это так? а если присоединяем, то увы жесткий диск гораздо медленней работает и поэтому дольше так? | |
|
|
|
|
|
|
|
для: TetRiska
(13.07.2011 в 18:42)
| | Когда как, если многотабличный запрос использует индексы, убирается в оперативной памяти (т.е. у сервера досточно ресурсов и он соответствующим образом настроен), то многотабличный запрос может выполняться быстрее множества однотабличных. Нередко бывает и наоборот - исследовать нужно в каждом конкретном случае. | |
|
|
|
|
|
|
|
для: cheops
(13.07.2011 в 19:00)
| | а не могли бы Вы посмотреть дампы таблиц дампы и самый первый блок пхп кода с запросом, все ли там верно по индексам? | |
|
|
|
|
|
|
|
для: 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). Индексы - это хорошо, но это не единственный и не всегда самый эффективный вариант оптимизации базы данных | |
|
|
|
|