I'm trying to optimize a ~100GB database. All data values are in one single innodb table, is this bad? Here's what a common query looks like:
SELECT `CensorCode`, `LocalDateTime`, `UTCOffset`, `DateTimeUTC`, `MethodID`, `SourceID`, `QualityControlLevelID`, `DataValue`, `OffsetTypeID`, `OffsetValue`, `d`.`SampleID`, `s`.`LabSampleCode`, `d`.`QualifierID`, `q`.`QualifierCode`
FROM (`datavalues` d)
LEFT JOIN `samples` s ON `d`.`SampleID` = `s`.`SampleID`
LEFT JOIN `qualifiers` q ON `d`.`QualifierID` = `q`.`QualifierID`
WHERE `d`.`SiteID` = '15'
AND `d`.`VariableID` = '8'
AND `d`.`LocalDateTime` >= '2009-04-18T00:02'
AND `d`.`LocalDateTime` <= '2009-04-20T00:02'
Here's what the explain statement on the above query looks like:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------------+---------------------------------------------+---------------------------------------------+---------+-------------------+---------+---------------------------------------------------------------------------+
| 1 | SIMPLE | d | index_merge | FK_DataValues_Variables,FK_DataValues_Sites | FK_DataValues_Sites,FK_DataValues_Variables | 4,4 | NULL | 1390435 | Using intersect(FK_DataValues_Sites,FK_DataValues_Variables); Using where |
| 1 | SIMPLE | s | eq_ref | PRIMARY | PRIMARY | 4 | odm.d.SampleID | 1 | |
| 1 | SIMPLE | q | eq_ref | PRIMARY | PRIMARY | 4 | odm.d.QualifierID | 1 |
Does this mean it's using indexes? If not, could someone explain how to create an index, I don't understand what it means. Any other suggestions would be greatly appreciated. Thanks in advance.
Also, here is the output from SHOW CREATE TABLE
| datavalues | CREATE TABLE `datavalues` (
`ValueID` int(11) NOT NULL AUTO_INCREMENT,
`DataValue` double NOT NULL,
`ValueAccuracy` double DEFAULT NULL,
`LocalDateTime` datetime NOT NULL,
`UTCOffset` double NOT NULL,
`DateTimeUTC` datetime NOT NULL,
`SiteID` int(11) NOT NULL,
`VariableID` int(11) NOT NULL,
`OffsetValue` double DEFAULT NULL,
`OffsetTypeID` int(11) DEFAULT NULL,
`CensorCode` varchar(50) NOT NULL DEFAULT 'nc',
`QualifierID` int(11) DEFAULT NULL,
`MethodID` int(11) NOT NULL DEFAULT '0',
`SourceID` int(11) NOT NULL,
`SampleID` int(11) DEFAULT NULL,
`DerivedFromID` int(11) DEFAULT NULL,
`QualityControlLevelID` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ValueID`),
UNIQUE KEY `DataValues_UNIQUE_DataValues` (`DataValue`,`ValueAccuracy`,`LocalDateTime`,`UTCOffset`,`DateTimeUTC`,`SiteID`,`VariableID`,`OffsetValue`,`OffsetTypeID`,`CensorCode`,`QualifierID`,`MethodID`,`SourceID`,`SampleID`,`DerivedFromID`,`QualityControlLevelID`),
KEY `FK_DataValues_Sources` (`SourceID`),
KEY `FK_DataValues_QualityControlLevels` (`QualityControlLevelID`),
KEY `FK_DataValues_OffsetTypes` (`OffsetTypeID`),
KEY `FK_DataValues_CensorCodeCV` (`CensorCode`),
KEY `FK_DataValues_Variables` (`VariableID`),
KEY `FK_DataValues_Methods` (`MethodID`),
KEY `FK_DataValues_Qualifiers` (`QualifierID`),
KEY `FK_DataValues_Samples` (`SampleID`),
KEY `FK_DataValues_Sites` (`SiteID`)
) ENGINE=InnoDB AUTO_INCREMENT=282507112 DEFAULT CHARSET=utf8 |
datavalues
with the Index Merge Intersection Access Algorithm(VariableID, SiteID, LocalDateTime)
will probably be more efficient - but it will certainly take some time (for the index) to be built in a 100GB table.