2013-05-15 40 views
0

我们有一个在MySQL数据库中相当静态的数据集,但是读取时间很糟糕(甚至在查询列的索引时也是如此)。理论上说,由于行是随机存储的(或者有时按照插入顺序存储),所以磁盘头必须扫描以找到不同的行,即使它知道索引所在的位置,而不是仅依次读取它们。在MySQL中更改磁盘上的数据组织

是否有可能改变订单数据存储在磁盘上,以便它可以顺序读取?不幸的是,我们现在不能添加更多的RAM来缓存所有的查询。如果可以更改订单,我们可以在订单内定义订单吗?如在列中排序,如果第一列相同,则按另一列排序。

这可能与索引有关吗?

其他详细信息:非关系型单表数据库,包含1600万行,1 GB数据总量,512 MB内存,Ubuntu 12.04上带有标准硬盘驱动器的MariaDB 5.5.30。另外这是一个使用OpenVZ的,2虚拟机专用核心E5-2620 CPU 2Ghz的

创建语法:

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=02 DEFAULT CHARSET=utf8; 

这需要很长的时间Select语句:

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

是的,它可能是随机磁盘I/O是你的问题;是的,有些事情可以用来重构磁盘上的数据。但是,在这样做之前,让我们检查一下您的查询是否使用了合适的索引;请显示表模式,查询及其执行计划:'SHOW CREATE TABLE foo','SELECT ...'和'EXPLAIN SELECT ...'。 – eggyal

+0

非常感谢您的回答。上面添加了语法和更多信息。 – AC360

+0

您的数据不是“随机”存储的,MySQL根据您的主键(“聚簇索引”)对数据进行排序。由于存储数据的文件碎片化,它可能会随机结束。从MySQL的角度来看,数据是通过'id'排序的 –

回答

0

MySQL只能选择一个 (这是有道理的,因为使用索引限制了结果,所以它不能确定这样的限制如何影响其他索引)。因此,它跟踪每个指数的基数并选择可能最具选择性的基数(即具有最高基数):在这种情况下,它选择了location指数,但通常会留下3,684条必须是获取并过滤Using where以找到与期望范围start_time匹配的那些。

你应该尝试创建一个composite index(location, start_time)

ALTER TABLE Events ADD INDEX (location, start_time) 
+0

非常感谢!它的工作速度更快!现在我想知道是否有任何其他查询优化,我们可以做?我应该研究什么东西来最大限度地提高磁盘I/O?再次感谢! – AC360

+0

@ AC360:对所做的一切都有权衡,所以要小心才能达到令人满意的性能;记住Knuth的格言“*过早优化是所有邪恶的根源*”。但是,如果性能仍然不理想,您应该首先*查找您的查询,以准确发现所花时间;如果磁盘I/O确实为您提供了重大问题,您可以考虑[分区](http://dev.mysql.com/doc/en/partitioning.html)数据 - 但不要在调整各种服务器之前引擎专用设置;但在许多情况下,硬件升级可能是首选。 – eggyal

+0

@eggyval:只是一个侧面说明:“*有道理*”并不完全正确。有几个DBMS可以有效地在查询中为一个表使用多个索引。 –