Оптимизация запроса

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
ZxcR_777
Сообщения: 21
Зарегистрирован: 2017.02.16, 16:17

Оптимизация запроса

Сообщение ZxcR_777 »

Добрый день, есть такая структура, Компании(id,name) Отделы(id,name,company_id) Позиции(id,name,position_id,company_id), Сотрудники(id,fullname, ..... , status) - анкетные данные сотрудника, status - показывает анкета принята и или ещё на рассмотрении и находится в заявках,(у анкеты 2 состояния - принят и в заявках),
Belongs(id, employee_id - ссылка на анкету сотрудников, work_status, company_id, department_id, position_id,...) - здесь хранятся должности сотрудников в компании, связь 1:M, т.е у одного сотрудника может быть несколько должностей , work_status - показывает сотрудник работает или уволен.
В сессии пользователя хранится список(массив) доступных ему department_id и каждый запрос сотрудников по отделам.

Код: Выделить всё

'query' => Employee::find()
	->alias('employee')
	->select('employee.id, employee.dob, employee.fullname,.......,
		company.name AS company_name, 
		department.name as department_name, 
		position.name as position_name, phone.num as tel, email.email as emails')
		 ->andWhere(['employee.status' => Employee::ACTIVE_STATUS])
		->joinWith(['belongs' => function ($q) {
		    return $q->joinWith(['company', 'department', 'position'], true, 'INNER JOIN');
		 	 }], true, 'LEFT JOIN')
		 ->andWhere(['belongs.work_status' => Belongs::WORKING_STATUS])
		 ->andFilterWhere(['like', 'LOWER(employee.fullname)', $qn])
		 ->andFilterWhere(['belongs.department_id' => isset($filter_param['department']) && $filter_param['department'] !='' ? (int) $filter_param['department'] : null])
		->joinWith(['phone_list'], true, 'LEFT JOIN')
		->joinWith(['email_list'], true, 'LEFT JOIN')
		->groupBy('employee.id')
		->asArray(),
Связь Employee с Belongs - выборка должностей по отделам из сессии.

Код: Выделить всё

public function getBelongs()
	{
		return $this->hasMany(Belongs::className(), ['employee_id' => 'id'])
			->alias('belongs')
			->andOnCondition(['belongs.department_id' => Yii::$app->session->get('dep_ids')])
			->indexBy('id');
	}
Делая запрос на 150 отделов ~ 900 cотрудников, получается примерно 5 секунд, по 2.5 на Запрос и Count(), GridView я использую картика.
Как можно ускорить запрос? бд кстати Mysql
Аватара пользователя
ElisDN
Сообщения: 5845
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Оптимизация запроса

Сообщение ElisDN »

Денормализацией в этих же таблицах или в ElasticSearch.
someweb
Сообщения: 552
Зарегистрирован: 2017.03.09, 10:12

Re: Оптимизация запроса

Сообщение someweb »

Может отпрофилировать запрос, посмотреть индексы, потюнить MySQL? Вроде не особо сложный запрос да и данных мало.
Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа. Роберт Шекли.
ZxcR_777
Сообщения: 21
Зарегистрирован: 2017.02.16, 16:17

Re: Оптимизация запроса

Сообщение ZxcR_777 »

Индексы стоят на полях по которым идут Join-ы и условия Where(), в дебаггере 2 основных запроса Count() И Select занимают по 2.1 - 2.2 cекунды
Nex-Otaku
Сообщения: 831
Зарегистрирован: 2016.07.09, 21:07

Re: Оптимизация запроса

Сообщение Nex-Otaku »

У тебя везде "joinWith(..., true, ...)" - зачем это? Ведь всё равно результат выводится в массив, а не в ActiveRecord. Поставь "false".

Кстати, сами SQL-запросы, которые генерируются, тоже неплохо было бы привести. Будет нагляднее.
ZxcR_777
Сообщения: 21
Зарегистрирован: 2017.02.16, 16:17

Re: Оптимизация запроса

Сообщение ZxcR_777 »

Код: Выделить всё

SELECT `employee`.`id`, `employee`.`dob`, `employee`.`vpn_num`, `employee`.`viber_num`, `employee`.`fullname`, `hr_employee_more_info`.`dream_city` AS `dream_city`, `company`.`name` AS `company_name`, `department`.`name` AS `department_name`, `position`.`name` AS `position_name`, `phone`.`num` AS `tel`, `email`.`email` AS `emails` FROM `hr_employee` `employee` LEFT JOIN `hr_employee_belongs` `belongs` ON (`employee`.`id` = `belongs`.`employee_id`) AND (`belongs`.`department_id` IN ('25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '70', '72', '73', '74', '75', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '132', '134', '135', '136', '137', '138', '146', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '160', '161', '162', '163', '164', '165', '166', '167', '169', '171', '172', '173', '174', '175', '176', '177', '178', '179', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '190', '191', '192', '193', '194', '195', '198', '199', '200')) INNER JOIN `hr_company` `company` ON `belongs`.`company_id` = `company`.`id` INNER JOIN `hr_department` `department` ON `belongs`.`department_id` = `department`.`id` INNER JOIN `hr_position` `position` ON `belongs`.`position_id` = `position`.`id` LEFT JOIN `hr_employee_phones` `phone` ON `employee`.`id` = `phone`.`employee_id` LEFT JOIN `hr_employee_emails` `email` ON `employee`.`id` = `email`.`employee_id` LEFT JOIN `hr_employee_more_info` ON employee.id = hr_employee_more_info.employee_id WHERE (`employee`.`status`=1) AND (`belongs`.`work_status`=1) GROUP BY `employee`.`id` ORDER BY `employee`.`fullname` LIMIT 20 
Запрос выборки
dmg
Сообщения: 685
Зарегистрирован: 2012.10.15, 03:09

Re: Оптимизация запроса

Сообщение dmg »

EXPLAIN делали ?
Ответить