MySQL - ускорение запросов, исключение сортировки файлов и временное
Мой запрос MySQL медленный У меня есть 3 таблицы: вакансии (200 тыс. Записей), местоположения (300 тыс.), Должности (700 тыс.).
SELECT
j.job_offerid
FROM `job_offer` AS j
INNER JOIN `job_offer_localitymap` AS d ON d.`job_offerid` = j.`job_offerid` AND
`gps_localityid` IN(35, 3301, 3302, 3303, 3305, 3306, 3307, 3308, 124, 3811, 3805, 3709, 3808, 3809)
WHERE
j.`status` = 1 AND
j.`job_offerid` IN(
SELECT `job_offerid`
FROM `job_offer_positionmap`
WHERE `cb_job_positionid` IN (1001, 6, 629, 7, 8, 9, 10, 11, 12, 13, 1, 15, 16, 17))
ORDER BY j.`job_offerid` DESC
LIMIT 3
Я должен фильтровать позиции и местности, поэтому я использовал IN.
ОБЪЯСНИТЕ: Используя где; Использование индекса; Используя временные; Использование сортировки файлов; Начать временный
Схема таблицы только с используемыми строками:
CREATE TABLE `job_offer` (
`job_offerid` int(13) NOT NULL AUTO_INCREMENT,
`status` int(13) NOT NULL DEFAULT '1',
PRIMARY KEY (`job_offerid`),
KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `job_offer_localitymap` (
`job_offer_localitymapid` int(13) NOT NULL AUTO_INCREMENT,
`gps_localityid` int(13) NOT NULL,
`job_offerid` int(13) NOT NULL,
PRIMARY KEY (`job_offer_localitymapid`),
KEY `gps_localityid` (`gps_localityid`),
KEY `job_offerid` (`job_offerid`),
KEY `gps_localityid_job_offerid` (`gps_localityid`,`job_offerid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
CREATE TABLE `job_offer_positionmap` (
`job_offer_positionmapid` int(13) NOT NULL AUTO_INCREMENT,
`cb_job_positionid` int(13) NOT NULL,
`job_offerid` int(13) NOT NULL,
PRIMARY KEY (`job_offer_positionmapid`),
KEY `cb_job_positionid` (`cb_job_positionid`),
KEY `job_offerid` (`job_offerid`),
KEY `cb_job_positionid_job_offerid` (`cb_job_positionid`,`job_offerid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
Индексы есть везде.
Спасибо за любой совет
2 ответа
Ваше объединение выиграет от составного
job_offer_localitymap.(job_offerid,gps_localityid)
То есть, идти противоположным путем, чем ваш нынешний композит в этой таблице.
Таким образом, вы можете отбросить эти два:
KEY `gps_localityid` (`gps_localityid`),
KEY `job_offerid` (`job_offerid`),
Как вы тогда оставили бы с двумя составными индексами, с большинством левого из каждого, используемого другими запросами, которые выиграли от вышеупомянутых двух, я только что сказал, чтобы отбросить
В строке запроса 5 будьте последовательны и используйте псевдоним j
как я должен был охотиться (не долго), чтобы увидеть, какой стол
На мой взгляд, ключ status
(status
) в job_offer может быть относительно бесполезным, но я не знаю вас других запросов. Но поскольку у вас тонкие типы данных, составной элемент job_offer(job_offerid,status) может заставить многие ваши запросы работать, как это было бы covering index
не нужно идти за страницей данных.
Что касается job_offer_positionmap
, это может быть объединение, удаляющее медленный подзапрос и выбор разработчика для добавления там композита. Концептуально это соединение похоже на первое.
Я не вижу никаких проблем с предложениями in в целом, так как оптимизатор mysql CBO должен решать эту проблему.
Но это всего лишь предложения, поскольку добавление индексов не лишено недостатков. Это хрупкое уравновешивание, но, в конце концов, вы можете обнаружить, что этот запрос не только летает, но и ваши другие.
Вы используете join
для фильтрации. Так что я бы перенес эту логику в where
пункт:
SELECT j.job_offerid
FROM `job_offer`
WHERE j.`status` = 1 AND
j.`job_offerid` IN (SELECT jop.`job_offerid`
FROM `job_offer_positionmap` jop
WHERE `cb_job_positionid` IN (1001, 6, 629, 7, 8, 9, 10, 11, 12, 13, 1, 15, 16, 17)
) AND
j.`job_offerid` IN (SELECT jop.`job_offerid`
FROM `job_offer_localitymap` jol
WHERE jol.gps_localityid IN (35, 3301, 3302, 3303, 3305, 3306, 3307, 3308, 124, 3811, 3805, 3709, 3808, 3809)
)
ORDER BY j.`job_offerid` DESC
LIMIT 3;
Затем для этого запроса вы хотите следующие индексы:
- job_offer (статус, job_offerid desc)
- job_offer_positionmap (cb_job_positionid, job_offerid)
- job_offer_localitymap (gps_localityid, job_offerid)
Результирующий запрос должен использовать первый индекс для фильтрации и order by
пункт. Затем он будет использовать два других индекса для фильтрации.