Оптимизировать MySQL запрос на соединение для удаления Использовать временный и использовать индекс? - PullRequest
1 голос
/ 27 июня 2011

У меня запрос с ORDER BY name, а индекс name игнорируется.

Как я могу оптимизировать запрос для использования индекса и избавиться от Using temporary из EXPLAIN?

У меня включен log-queries-not-using-indexes, и я вижу этот запрос тысячи раз.

Вот запрос:

SELECT l.parent_id, j.id, j.location_id, j.currency, j.frequency, ROUND((j.salary_min + j.salary_max)/2) as salary 
FROM jobs AS j
JOIN location AS l
    ON j.location_id = l.id
WHERE j.salary_min !=0 
    AND j.status != 'Rejected'      
    AND l.published =1
    AND date_sub(now(), interval 1 month) <= j.effected_date
ORDER BY l.name

Объяснение:

+----+-------------+-------+--------+----------------------------------+---------------+---------+----------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                    | key           | key_len | ref                        | rows | Extra                                        |
+----+-------------+-------+--------+----------------------------------+---------------+---------+----------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | j     | range  | effected_date,location_id,status | effected_date | 9       | NULL                       |  562 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | l     | eq_ref | PRIMARY                          | PRIMARY       | 4       | esljw_joomla.j.location_id |    1 | Using where                                  |
+----+-------------+-------+--------+----------------------------------+---------------+---------+----------------------------+------+----------------------------------------------+
2 rows in set (0.01 sec)

И структура таблицы:

CREATE TABLE IF NOT EXISTS `jobs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `location_id` varchar(255) NOT NULL,
  `status` varchar(255) DEFAULT NULL,
  `currency` varchar(255) DEFAULT NULL,
  `salary_min` int(11) DEFAULT NULL,
  `salary_max` int(11) DEFAULT NULL,
  `effected_date` datetime DEFAULT NULL,
  `frequency` varchar(255) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `effected_date` (`effected_date`),
  KEY `location_id` (`location_id`),
  KEY `status` (`status`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=10130 ;

CREATE TABLE IF NOT EXISTS `location` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=304 ;

Ответы [ 3 ]

0 голосов
/ 27 июня 2011

Это потому, что вы перечислили job первым.Измените порядок таблиц следующим образом:

SELECT l.parent_id, j.id, j.location_id, j.currency, j.frequency, ROUND((j.salary_min + j.salary_max)/2) as salary 
FROM location AS l
JOIN jobs AS j  ON j.location_id = l.id
WHERE j.salary_min !=0 
AND j.status != 'Rejected'      
AND l.published =1
AND date_sub(now(), interval 1 month) <= j.effected_date
ORDER BY l.name

Попробуйте и напишите, как это происходит.

0 голосов
/ 27 июня 2011

Много раз я выполнял запросы, в которых у вас есть правильная первичная таблица, как первая в запросе, с хорошими индексами, добавление только STRAIGHT_JOIN может исправить запрос.Итак, с вашими существующими критериями вы должны быть в порядке с вашим индексом даты и использовать его в качестве основных критериев ... таких как

SELECT STRAIGHT_JOIN
      L.Parent_ID, 
      J.id, 
      J.location_id, 
      J.currency, 
      J.frequency, 
      ROUND(( J.salary_min + J.salary_max) / 2 ) as Salary 
   FROM
      jobs J
         join Location L
            on J.Location_ID = L.ID
            AND L.Published = 1
   WHERE
          J.Effected_Date >= date_sub(now(), interval 1 month)
      AND J.salary_min != 0
      AND J.status != 'Rejected'
   ORDER BY 
      L.name
0 голосов
/ 27 июня 2011
  1. Добавить published + id составной индекс к location таблице
  2. Переместить условие l.published =1 в предложение ON

Это то, что вы можете сделать в вашем случае. Но, вероятно, вы никогда не избавитесь от using temporary, поскольку вы сортируете не по основной таблице, а по объединенной таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...