我有一个mysql表,其中包含以下字段:rangeFrom
和rangeTo
。
我想在联接中请求具有以下条件的行:rangeFrom >= ? AND rangeTo <=?
。
EXPLAIN SELECT *
FROM Version
JOIN Contract FORCE INDEX FOR JOIN (versionRangeFrom)
ON Version.id >= Contract.versionRangeFrom
AND Version.id <= Contract.versionRangeTo
WHERE Version.completedAt = '2016-06-06 10:00:01';
哪个mysql解释如下:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Version ref PRIMARY,completedAt completedAt 6 const 1 NULL
1 SIMPLE Contract ALL versionRangeFrom NULL NULL NULL 640744 Range checked for each record (index map: 0x8)
所以它必须工作640744行,大约需要1-2秒。
但是,在queryworks中插入版本ID
EXPLAIN SELECT *
FROM Contract
WHERE 5 >= Contract.versionRangeFrom AND 5 <= Contract.versionRangeTo;
然后这样解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Contract range versionRangeFrom versionRangeFrom 4 NULL 534 Using index condition; Using where
所以在这种情况下,mysql只能运行534行,而且只需要大约30ms。
那么我该如何正确地准备这样的范围检查。在这些情况下,似乎mysql无法使用索引。我可以通过使用2个查询解决它,但我宁愿有一个。
这里有更多模式:
CREATE TABLE `Version` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`completedAt` datetime DEFAULT NULL,
`createdAt` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `completedAt` (`completedAt`)
)
CREATE TABLE `Contract` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`contractId` bigint(20) unsigned NOT NULL,
`startAt` bigint(20) NOT NULL DEFAULT '0',
`endAt` bigint(20) NOT NULL DEFAULT '0',
`tradeStartAt` bigint(20) NOT NULL DEFAULT '0',
`tradeEndAt` bigint(20) NOT NULL DEFAULT '0',
`latestAiId` bigint(20) NOT NULL DEFAULT '0',
`type` varchar(4) COLLATE utf8_unicode_ci NOT NULL,
`daPreis` int(11) NOT NULL DEFAULT '0',
`lastTradePreis` int(11) NOT NULL DEFAULT '0',
`lastTradeVol` int(11) NOT NULL DEFAULT '0',
`VWAID` double NOT NULL DEFAULT '0',
`versionRangeFrom` int(10) unsigned NOT NULL,
`versionRangeTo` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `tradeStartAt` (`tradeStartAt`),
KEY `contractId` (`contractId`),
KEY `versionRangeFrom` (`versionRangeFrom`)
)
答案 0 :(得分:0)
与&#39; 5&#39;不同的值。不需要只看534行。
问题(x < from AND x > to
)非常重要,而且没有简单的答案。
缩小表格大小会有所帮助。当一些较小的数据类型就足够时,不要使用BIGINT
(8个字节)。
也许唯一真正的解决方案是对架构和代码进行重大改进。请参阅my blog。
修改强>
在某些情况下,此子查询可以有效地用于查找相关行:
( SELECT Contract.id FROM ...
WHERE Version.id >= Contract.versionRangeFrom
ORDER BY versionRangeFrom
LIMIT 1 )