Ich habe eine MySQL-Tabelle, die die Felder enthält: rangeFrom
und rangeTo
.Effiziente Auswahl auf einer großen Tabelle von Bereichen
Ich möchte Zeilen mit einer Bedingung wie anfordern: rangeFrom >= ? AND rangeTo <=?
innerhalb einer Verbindung.
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';
Welche mysql erklärt wie folgt aus:
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)
So hat es aber 640.744 Zeilen arbeiten, die etwa 1-2 Sekunden dauert.
jedoch Einsetzen der Version-ID in den queryworks feinen
EXPLAIN SELECT *
FROM Contract
WHERE 5 >= Contract.versionRangeFrom AND 5 <= Contract.versionRangeTo;
Dies erklärt sich dann wie folgt aus:
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
Also in diesem Fall mysql nur wenn 534 Zeilen geht und das dauert nur etwa 30 ms .
Also wie bereite ich mich auf eine solche Bereichsprüfung richtig vor. Es scheint, dass mysql in diesen Fällen keine Indizes verwenden kann. Ich kann mit 2 Abfragen umgehen, aber ich hätte lieber eine.
Hier mehr Schemata:
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`)
)
Bitte senden Sie ein Schema und Beispielabfragen, idealerweise mit einem ERKLÄREN. "Es scheint, dass MySQL keine Indizes verwenden kann", ist nicht wirklich etwas, mit dem wir helfen können. –
@NevilleK getan. Und ich dachte, dass mein Problem ein wenig anders ist, als ich dachte, und auch ich habe einen Workaround gefunden. – Nemo64