У меня две таблицы: Таблица 1:
CREATE TABLE `lk_transaction_types` (
`transactionTypeID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`isActive` tinyint(2) unsigned NOT NULL,
`code` varchar(8) NOT NULL,
`description` varchar(150) NOT NULL,
`isInbound` tinyint(2) unsigned NOT NULL DEFAULT '1',
`isOutbound` tinyint(2) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`transactionTypeID`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;
Таблица 2:
CREATE TABLE `ediLoad` (
`loadID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`processID` int(10) unsigned NOT NULL,
`success` tinyint(2) unsigned NOT NULL DEFAULT '0',
`transactionTypeID` tinyint(2) unsigned DEFAULT NULL,
`escoID` int(10) unsigned DEFAULT NULL,
`ldcID` int(10) unsigned DEFAULT NULL,
`commodityType` tinyint(3) unsigned NOT NULL DEFAULT '0',
`filename` varchar(150) NOT NULL,
`loadDate` datetime NOT NULL,
`processed` tinyint(2) unsigned NOT NULL DEFAULT '0',
`processedDate` datetime DEFAULT NULL,
`dataApplied` tinyint(2) unsigned NOT NULL DEFAULT '0',
`dataAppliedDate` datetime DEFAULT NULL,
`errorID` tinyint(3) unsigned DEFAULT NULL,
`error` tinyint(2) unsigned DEFAULT '0',
`warning` tinyint(2) unsigned DEFAULT '0',
PRIMARY KEY (`loadID`),
KEY `idx_processID` (`processID`,`transactionTypeID`,`escoID`),
KEY `idx_escoID` (`escoID`),
KEY `idx_filename` (`success`,`filename`),
KEY `idx_bulk` (`processed`,`loadDate`),
KEY `idx_loadDate` (`loadDate`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=35086005 DEFAULT CHARSET=utf8;
При попытке выполнить простой запрос он не использует первичный ключ в таблице lk_transaction_types:
SELECT COUNT(0)
FROM edi.ediLoad l
INNER JOIN edi.lk_transaction_types lk
ON lk.transactionTypeID = l.transactionTypeID
WHERE l.escoID = 2
AND lk.isActive = 1
AND lk.isInbound = 1;
Запрос выполняется очень медленно. Итак, я бегу объяснять
EXPLAIN SELECT COUNT(0)
FROM edi.ediLoad l
INNER JOIN edi.lk_transaction_types lk
ON lk.transactionTypeID = l.transactionTypeID
WHERE l.escoID = 2
AND lk.isActive = 1
AND lk.isInbound = 1;
Это возвращает
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE lk NULL ALL PRIMARY NULL NULL NULL 31 3.23 Using where
1 SIMPLE l NULL ref idx_escoID idx_escoID 5 const 71580 10.00 Using where
Это похоже на простой запрос с одним соединением по первичному ключу. Почему не используется первичный ключ? Я даже пробовал добавить в соединение FORCE INDEX FOR JOIN (PRIMARY), но он по-прежнему не использует первичный ключ. Любая помощь была бы замечательной. Спасибо!






Чтобы немного подробнее рассказать о том, что @Uueerdo говорит в комментарии выше: MySQL не может использовать индекс idx_processID в этом случае, поскольку transactionTypeID является вторым столбцом в индексе, а первый столбец (processID) не является частью оператора where .
Если вы добавите новый ключ только с transactionTypeID, он будет использован.
От https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html:
MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on. If you specify the columns in the right order in the index definition, a single composite index can speed up several kinds of queries on the same table.
Добавление ключа ускоряет запрос, но просто за счет фильтрации ediLoad. Он по-прежнему не использует ПК для соединения
@MichaelShapiro: тип данных для ediLoad.transactionTypeID - tinyint (2), а в lk_transaction_types - int (10), что, как я полагаю, является проблемой. Сделайте их равными (предположительно, оба int (10)), и я считаю, что у вас все будет в порядке.
Несмотря на то, что концептуально, WHERE обрабатывается после соединения, MySQL пытается уменьшить количество соединяемых строк, проверяя сначала соответствующие критерии в WHERE. Поскольку
ediLoadне имеет индекса, начинающегося сtransactionTypeID, и представляет собой большую таблицу; он, вероятно, игнорирует относительно бесполезный pkedi.