我们在MySQL数据库中有一个相当静态的数据集,但读取时间很糟糕(即使查询列上的索引也是如此)。理论上,由于行是随机存储的(或者有时按插入顺序存储),磁盘头必须扫描以找到不同的行,即使它知道它们归因于索引的位置,而不是仅按顺序读取它们。
是否可以更改订单数据存储在磁盘上以便可以按顺序读取?不幸的是,我们现在无法添加更多的RAM来缓存所有查询。如果可以更改订单,我们可以在订单中定义订单吗?如同,按某个列排序,如果第一列相等,则按另一列排序。
这可能与指数有关吗?
其他详细信息:非关系型单表数据库,包含1600万行,1 GB数据,512 MB RAM,带有标准硬盘的Ubuntu 12.04上的MariaDB 5.5.30。这也是使用OpenVZ的虚拟机,2个专用核心E5-2620 2Ghz CPU
创建语法:
CREATE TABLE `Events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`provider` varchar(10) DEFAULT NULL,
`location` varchar(5) DEFAULT NULL,
`start_time` datetime DEFAULT NULL,
`end_time` datetime DEFAULT NULL,
`cost` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `provider` (`provider`),
KEY `location` (`location`),
KEY `start_time` (`start_time`),
KEY `end_time` (`end_time`),
KEY `cost` (`cost`)
) ENGINE=InnoDB AUTO_INCREMENT=16321002 DEFAULT CHARSET=utf8;
选择需要很长时间的语句:
SELECT *
FROM `Events`
WHERE `Events`.start_time >= '2013-05-03 23:00:00' AND `Events`.start_time <= '2013-06-04 22:00:00' AND `FlightRoutes`.location = 'Chicago'
解释选择:
1 SIMPLE Events ref location,start_time location 18 const 3684 Using index condition; Using where
答案 0 :(得分:0)
MySQL只能选择要过滤的一个索引(这是有道理的,因为使用索引来限制结果,然后它无法确定这种限制如何影响其他索引)。因此,它跟踪每个索引的基数并选择可能最具选择性的基数(即具有最高基数):在这种情况下,它选择了location
索引,但通常会留下3,684个必须提取然后过滤Using where
的记录才能找到符合start_time
所需范围的记录。
您应该尝试在(location, start_time)
上创建composite index:
ALTER TABLE Events ADD INDEX (location, start_time)