Answer the question
In order to leave comments, you need to log in
Normalization and fight against “using temporary; using filesort"
Database of employees.
CREATE TABLE IF NOT EXISTS `employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) NOT NULL,
`surname` varchar(150) NOT NULL,
`city_id` int(3) unsigned NOT NULL DEFAULT '0',
`deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
`last_vacation_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT 'Последнее время отпуска (timestamp)',
PRIMARY KEY (`id`),
KEY `deleted` (`deleted`,`last_vacation_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
-- --------------------------------------------------------
--
-- Таблица с возрастами детей работников
--
CREATE TABLE IF NOT EXISTS `employee_child_age` (
`employee_id` int(11) unsigned NOT NULL,
`child_age` int(3) unsigned NOT NULL DEFAULT '0',
KEY `employee_id` (`employee_id`,`child_age`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Таблица с городами
--
CREATE TABLE IF NOT EXISTS `employee_city` (
`city_id` int(11) NOT NULL AUTO_INCREMENT,
`city_name` varchar(100) NOT NULL,
PRIMARY KEY (`city_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=44 ;
-- --------------------------------------------------------
--
-- Таблица с различным пометками к работникам
--
CREATE TABLE IF NOT EXISTS `employee_mark` (
`employee_id` int(11) unsigned NOT NULL,
`mark_name` varchar(15) CHARACTER SET utf8 NOT NULL,
KEY `employee_id` (`employee_id`,`mark_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
SELECT e.*, city.* FROM employee AS e
INNER JOIN employee_child_age AS age ON age.employee_id=e.id AND age.child_age>10
INNER JOIN employee_city AS city ON city.city_id=e.city_id
WHERE e.deleted=0 ORDER BY e.last_vacation_time;
SELECT e.*, city.* FROM employee AS e
INNER JOIN employee_child_age AS age ON age.employee_id=e.id AND age.child_age>10
INNER JOIN `employee_mark` AS mark ON mark.employee_id=e.id AND mark.mark_name='frg'
INNER JOIN employee_city AS city ON city.city_id=e.city_id
WHERE e.deleted=0 ORDER BY e.last_vacation_time;
Answer the question
In order to leave comments, you need to log in
Definitely, you need to create indexes on secondary keys in all tables (just in case, let me remind you that a secondary key is a field that is used in JOIN), as well as an index on last_vacation_time in the employee table - there is simply nothing to optimize without these indexes. An index on the fields on which the selection takes place will also help.
To begin with, it is worth trying to remove AND from the JOIN condition and move it to the WHERE block - there is only one sense, but the MySQL optimizer has never been smart and quick-witted.
It is also worth trying to use one ENGINE for all tables.
As a last resort, I personally would play with the order of the JOINs. I DO NOT know if this order affects the query plan in MySQL, but I heard something bad. Perhaps this feature was fixed in the latest version.
- By the way, about the data scheme. I would make a dictionary of label types (names) so as not to duplicate string information. And vacations would store everything in a separate table, not just the last one. But first, of course, you need to learn how to build fast queries.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question