次のように、2 つのテーブルを結合する 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';
この問題は、classification_entity_map テーブルのプライマリ インデックスではなく fk_classification_entity_map_1 インデックスを使用しているため、クエリが mysql ワークベンチで予想よりも長くかかることです (9.4 秒)。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
convert を使用しないクエリの Explain 出力は以下のとおりで、可能な限り PRIMARY が表示されます (ただし、convert を使用するクエリでは表示されません)。
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