0

我们有一个在 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
4

1 回答 1

0

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

您应该尝试在以下位置创建复合索引(location, start_time)

ALTER TABLE Events ADD INDEX (location, start_time)
于 2013-05-15T05:30:28.993 回答