Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Как оптимизировать запросы в mysql?
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Как оптимизировать запросы в mysql?

Страниц (1): [1]
 

1. x-miller-x - 26 Апреля, 2017 - 06:36:20 - перейти к сообщению
Есть запросы которые при меньшей нагрузке выполняются меньше секунды, потом как бывает некая нагрузка 300-400 юзеров онлайн, начинают выполнятся от 5 секунд до 120с+

Запрос №1
CODE (text):
скопировать код в буфер обмена
  1. SELECT count(DISTINCT product.id)
  2. FROM `product`
  3. JOIN `city` ON city.id=product.city_id
  4. JOIN `company` ON company.id=product.company_id
  5. WHERE ((((`product`.`id` in (
  6.           select product_id from product_to_city
  7.           join city on (city.id = product_to_city.city_id)
  8.           where city.id = 104 or city.parent_id = 104
  9.         )))) AND (`product`.`publish` = 1 AND `product`.`archive` != 1 AND `product`.`delete` != 1));


Запрос №2
CODE (text):
скопировать код в буфер обмена
  1. SELECT count(*)
  2. FROM (SELECT `product`.`id`, `product`.`position`, `product`.`description`, `product`.`city_id`,  `production`.`price`,  `production`.`company_id`, `company`.`company_type`, `city`.`name` AS `city_name`
  3. FROM `product_to_tag` `p2t`
  4. JOIN `product` ON product.id = p2t.product_id
  5. JOIN `product_to_city` `ptc` ON product.id = ptc.product_id
  6. JOIN `city` `c` ON c.id = ptc.city_id
  7. LEFT JOIN `city` `city` ON city.id=product.city_id
  8. LEFT JOIN `company` ON company.id=product.company_id
  9. WHERE ((((`product`.`id` in (
  10.           select product_id from product_to_city
  11.           join city on (city.id = product_to_city.city_id)
  12.           where city.id = 1 or city.parent_id = 1
  13.         )))) AND (`product`.`publish` = 1 AND `product`.`archive` != 1 AND `product`.`delete` != 1)) AND (product.id !=  513568) AND (c.id = 1 or c.parent_id = 1) AND ((`p2t`.`tag_id` IN (14, 30, 37, 500)))
  14. GROUP BY `product`.`id`
  15. ORDER BY `product`.`timestamp_update` DESC) as count;



в логах долгих запросов после второго запроса даже простые запросы медленно начинают выполнятся
CODE (text):
скопировать код в буфер обмена
  1.  
  2. # Query_time: 256.971239 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
  3. UPDATE product SET `view_count` = `view_count` + 1 WHERE id = '2797283';
  4.  
  5. # Query_time: 554.572351 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
  6. UPDATE product SET `view_count` = `view_count` + 1 WHERE id = '2156047';
  7.  
  8. # Query_time: 646.604457 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0
  9. UPDATE product SET `view_count` = `view_count` + 1 WHERE id = '2104649';


как еще оптимизировать? Индексы все расставлены
2. Мелкий - 26 Апреля, 2017 - 09:04:06 - перейти к сообщению
Первый запрос:
зачем вам вообще джойны и distinct? За отсечением отсутствующих городов и кампаний должны FK следить и не допускать такое в принципе. in subquery - в зависимости от версии mysql и количества данных. Имеет смысл попробовать переписать в join.

Второй:
зачем вообще внешний селект? Зачем группировка, сортировка и чуть менее чем все джойны?

Апдейты очевидно ждут блокировки. Если у вас единственно вменяемый innodb (и изоляция транзакций не serializable) - то селект их заблокировать не мог, блокирует кто-то другой.
Если какой-нибудь myisam - то разумеется все они дерутся за табличную блокировку.
3. x-miller-x - 26 Апреля, 2017 - 11:16:04 - перейти к сообщению
1. distinct уберу, а джойны просто нужны еще когда надо делать выборку по полям этих таблицы

переписал subquery в Join

CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT count(DISTINCT product.id)
  3.     FROM `product`
  4.     JOIN `product_to_city` ON `product`.`publish` = 1
  5.         AND `product`.`archive` != 1 AND `product`.`delete` != 1
  6.         AND `product_to_city`.`product_id` = `product`.`id`
  7.     JOIN `city` AS `c` ON (`c`.`id` = 104 OR `c`.`parent_id` = 104)
  8.         AND `c`.`id` = `product_to_city`.`city_id`
  9.     JOIN `city` ON `city`.`id` = `product`.`city_id`
  10.     JOIN `company` ON `company`.`id` = `product`.`company_id`
  11.  


2. group нужен для того чтобы группировать по product.id так как при обычной выборке без group туда попадают дубли, соотвественно когда count внутри этого запроса то получаем несколько строк с количеством товаров у этого тега, поэтому пришлось написать внешний count чтобы считать общее количество записей


3. Насчет MyIsam там только одна таблица MyIsam и то не участвует в выборке, только записываю данные, думаете он блокирует?

 

Powered by ExBB FM 1.0 RC1