Я написал систему запросов на работу на PHP с базой данных MySQL, и у меня возникла проблема с медленным запросом.
Моя схема (упрощенная) выглядит следующим образом:
tbl_job
job_id
Работа по убыванию
requester_user_id
tbl_user
user_id
имя_пользователя
tbl_workermap
workermap_id
job_id
worker_user_id
Таблица, содержащая задания, пользовательская таблица возможных работников и таблица для сопоставления рабочих мест с заданиями. Работа может иметь одного или нескольких работников, работник может иметь одну или несколько работ.
tbl_user содержит как пользователей, которые запрашивают работу, так и тех, кто работает над заданиями, поэтому идентификаторы пользователей хранятся в файле worker_user_id в tbl_workermap и requestter_user_id в tbl_job
Когда задание регистрируется, оно создает запись в tbl_job, но ничего в tbl_workermap, пока кто-то специально не назначит работника. Это означает, что когда я запрашиваю задания, я делаю это с левым соединением, поскольку в tbl_workermap нет записей для каждого задания:
SELECT
job.job_id,
job.job_desc,
workermap.worker_user_id,
worker.worker_name
FROM tbl_job AS job
LEFT JOIN tbl_workermap AS workermap
ON job.job_id = workermap.job_id
LEFT JOIN tbl_user AS worker
ON workermap.worker_user_id = worker.user_id
Система использовалась некоторое время, и теперь у меня есть около 8000 записей в tbl_job и 7000 в tbl_workermap, и для получения всех результатов требуется более 4 секунд. Запрос EXPLAIN показывает соединение tbl_workermap, возвращающее около 7000 строк и «Использование где; Использование буфера соединения (блочный вложенный цикл)».
Что я могу сделать, чтобы ускорить это?
РЕДАКТИРОВАТЬ: добавить информацию таблицы
Я бы упростил объяснение, но вот фактическая структура таблицы. Есть еще объединения, но единственной проблемной является tbl_workermap:
CREATE TABLE `tbl_job` (
`job_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`job_title` varchar(100) DEFAULT NULL,
`job_description` text,
`job_added_datetime` int(11) DEFAULT '0',
`job_due_datetime` int(11) NOT NULL DEFAULT '0',
`job_time_estimate` int(11) DEFAULT NULL,
`job_additional_fields` text,
`addedby_user_id` int(11) NOT NULL DEFAULT '0',
`requester_user_id` int(11) NOT NULL DEFAULT '0',
`worker_user_id` int(11) NOT NULL DEFAULT '0',
`job_active` tinyint(4) NOT NULL DEFAULT '1',
`site_id` tinyint(4) NOT NULL DEFAULT '1',
`status_id` int(11) NOT NULL DEFAULT '1',
`estimategroup_id` int(11) DEFAULT '1',
`brand_id` int(11) DEFAULT '1',
`job_isproject` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`job_id`),
FULLTEXT KEY `job_title` (`job_title`,`job_description`,`job_additional_fields`)
) ENGINE=MyISAM AUTO_INCREMENT=8285 DEFAULT CHARSET=latin1
CREATE TABLE `tbl_user` (
`user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_shortname` varchar(30) DEFAULT NULL,
`user_name` varchar(30) DEFAULT NULL,
`user_password` varchar(50) DEFAULT NULL,
`user_password_reset_uuid` varchar(50) DEFAULT NULL,
`user_email` varchar(50) DEFAULT NULL,
`user_description` text,
`user_sortorder` int(11) NOT NULL DEFAULT '0',
`user_isworker` tinyint(4) NOT NULL DEFAULT '0',
`user_active` tinyint(4) NOT NULL DEFAULT '1',
`site_id` tinyint(4) NOT NULL DEFAULT '0',
`user_avatar_file_id` int(11) DEFAULT NULL,
`user_avatar_hub_url` varchar(100) DEFAULT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM AUTO_INCREMENT=917 DEFAULT CHARSET=latin1
CREATE TABLE `tbl_workermap` (
`workermap_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`job_id` int(11) DEFAULT NULL,
`workermap_datetime_added` int(11) DEFAULT NULL,
`workermap_datetime_removed` int(11) DEFAULT NULL,
`worker_user_id` int(11) DEFAULT NULL,
`addedby_user_id` int(11) DEFAULT NULL,
`removedby_user_id` int(11) DEFAULT NULL,
`site_id` int(11) DEFAULT NULL,
`workermap_isassigned` int(11) DEFAULT NULL,
`workermap_active` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`workermap_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7145 DEFAULT CHARSET=latin1
ПОКАЗАТЬ ИНДЕКС
+---------+---+-----------+---+-----------------------+------+------+------+------+-----+----------+--+--+
| tbl_job | 0 | PRIMARY | 1 | job_id | A | 8283 | NULL | NULL | | BTREE | | |
+---------+---+-----------+---+-----------------------+------+------+------+------+-----+----------+--+--+
| tbl_job | 1 | job_title | 1 | job_title | NULL | 1 | NULL | NULL | YES | FULLTEXT | | |
| tbl_job | 1 | job_title | 2 | job_description | NULL | 1 | NULL | NULL | YES | FULLTEXT | | |
| tbl_job | 1 | job_title | 3 | job_additional_fields | NULL | 1 | NULL | NULL | YES | FULLTEXT | | |
+---------+---+-----------+---+-----------------------+------+------+------+------+-----+----------+--+--+
+----------+---+---------+---+---------+---+-----+------+------+--+-------+--+--+
| tbl_user | 0 | PRIMARY | 1 | user_id | A | 910 | NULL | NULL | | BTREE | | |
+----------+---+---------+---+---------+---+-----+------+------+--+-------+--+--+
+---------------+---+---------+---+--------------+---+------+------+------+--+-------+--+--+
| tbl_workermap | 0 | PRIMARY | 1 | workermap_id | A | 7184 | NULL | NULL | | BTREE | | |
+---------------+---+---------+---+--------------+---+------+------+------+--+-------+--+--+
ПОЯСНИТЬ запрос
+---+--------+----------------+--------+---------+---------+------+-------------------------------+------+----------------------------------------------------+
| 1 | SIMPLE | job | ALL | NULL | NULL | NULL | NULL | 8283 | Using where; Using temporary; Using filesort |
+---+--------+----------------+--------+---------+---------+------+-------------------------------+------+----------------------------------------------------+
| 1 | SIMPLE | estimategroup | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.estimategroup_id | 1 | Using where |
| 1 | SIMPLE | brand | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.brand_id | 1 | Using index condition |
| 1 | SIMPLE | site | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.site_id | 1 | Using where |
| 1 | SIMPLE | addedby | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.addedby_user_id | 1 | Using index condition |
| 1 | SIMPLE | requester | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.requester_user_id | 1 | Using index condition |
| 1 | SIMPLE | worker | eq_ref | PRIMARY | PRIMARY | 4 | jobq.job.worker_user_id | 1 | Using index condition |
| 1 | SIMPLE | status | ALL | PRIMARY | NULL | NULL | NULL | 6 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | workermap | ALL | NULL | NULL | NULL | NULL | 7184 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | user_workermap | eq_ref | PRIMARY | PRIMARY | 4 | jobq.workermap.worker_user_id | 1 | Using where |
| 1 | SIMPLE | categorymap | ALL | NULL | NULL | NULL | NULL | 1 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | category | eq_ref | PRIMARY | PRIMARY | 4 | jobq.categorymap.category_id | 1 | Using where |
+---+--------+----------------+--------+---------+---------+------+-------------------------------+------+----------------------------------------------------+