我正在尝试优化连接两个表的 MYSQL 查询的执行,如下所示:
CREATE TABLE `CPP` (
`RecordEntryType` varchar(7) NOT NULL default '',
`PositionNumber` mediumint(9) NOT NULL default '0',
`FundId` smallint(6) default NULL,
`QuantityHeld` decimal(14,2) default NULL,
`MarketValue` decimal(14,2) default NULL,
`PeriodBeginDate` date default NULL,
`PeriodEndDate` date NOT NULL default '0000-00-00',
PRIMARY KEY (`PositionNumber`,`PeriodEndDate`,`RecordEntryType`),
KEY `Index1` (`FundId`,`PeriodBeginDate`,`PeriodEndDate`),
KEY `FundId_idx` (`FundId`),
KEY `PeriodBeginDate_idx` (`PeriodBeginDate`),
KEY `PeriodEndDate_idx` (`PeriodEndDate`),
KEY `PositionNumber_id` (`PositionNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `classification_entity_map` (
`entity_id` varchar(32) NOT NULL,
`entity_type` varchar(32) NOT NULL,
`scheme_id` int(11) NOT NULL,
`class_id` varchar(24) NOT NULL,
PRIMARY KEY (`entity_id`,`entity_type`,`scheme_id`),
KEY `fk_classification_entity_map_1` (`scheme_id`),
KEY `fk_class` (`class_id`),
CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `classification_hierarchy` (`external_id`),
CONSTRAINT `fk_scheme` FOREIGN KEY (`scheme_id`) REFERENCES `classification_schemes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
select cpp.*, cem.class_id from cpp
LEFT JOIN classification_entity_map cem
ON cem.entity_id = cpp.PositionNumber and cem.entity_type = 'Security'
AND cem.scheme_id = 9901
WHERE cpp.RecordEntryType = 'CURRENT'
AND ( cpp.MarketValue != 0 OR cpp.QuantityHeld != 0 )
AND FundId = 28
AND cpp.PeriodEndDate = '2013-09-30';
问题是查询在 mysql 工作台中花费的时间比预期的要长(9.4 秒),因为它使用的是 fk_classification_entity_map_1 索引而不是分类实体映射表上的主索引。cpp 有 626,648 行,cem 有 63,487 行。
我怀疑问题与 cem.entity_id 和 cpp.PositionNumber 的数据类型有关,但我不确定,因为它们无法更改。请帮忙。如果有帮助,我可以上传解释输出。
更多信息:将连接更改为 convert(cpp.PositionNumber, char(32)) 如下无济于事,因为时间长达 10 秒:
ON cem.entity_id = convert(cpp.PositionNumber, char(32)) and cem.entity_type = 'Security'
AND cem.scheme_id = 9901
不带转换的查询的解释输出如下,并尽可能地看到 PRIMARY(但不在带转换的查询中):
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE cpp index_merge Index1,FundId_idx,PeriodEndDate_idx FundId_idx,PeriodEndDate_idx 3,3 402 Using intersect(FundId_idx,PeriodEndDate_idx); Using where
1 SIMPLE cem ref PRIMARY,fk_classification_entity_map_1 fk_classification_entity_map_1 4 const 24100