【发布时间】:2015-03-07 22:48:38
【问题描述】:
我正在拔头发,试图找出我做错了什么。 表格很简单:
CREATE TABLE `icd_index` (
`icd` char(5) NOT NULL,
`core_id` int(11) NOT NULL,
`dx_order` tinyint(4) NOT NULL,
PRIMARY KEY (`icd`,`dx_order`,`core_id`),
KEY `core` (`core_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
如您所见,我创建了一个覆盖表的所有三列的覆盖索引,并在core_id 上创建了一个附加索引,用于潜在的连接。这是一个一对多的链接表,每个core_id 映射到一个或多个icd。该表包含 6500 万行。
所以,这就是问题所在。假设我想知道有多少人的 icd 代码为“25000”。 [那是糖尿病,如果你想知道的话]。我编写了一个如下所示的查询:
SELECT COUNT(core_id) FROM icd_index WHERE icd='25000'
这需要超过 60 秒才能执行。我原以为 icd 列在被覆盖的索引中排在第一位,因此计数会很快。
更令人困惑的是,一旦我运行了一次查询,它现在运行得非常快。我认为这是因为查询被缓存了,但即使我RESET QUERY CACHE,查询现在也可以在几分之一秒内运行。但是,如果我等待的时间足够长,它似乎又变慢了——我不知道为什么。
我遗漏了一些明显的东西。我需要一个单独的icd 索引吗?这是使用 65M 行可以获得的最佳性能吗?为什么运行查询然后重置缓存会影响速度?结果是否存储在索引中?
编辑:我正在运行 MySQL 5.6(以防万一)。
这是查询的EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE icd_index ref PRIMARY PRIMARY 15 const 910104 Using where; Using index
【问题讨论】:
-
你能试试
SELECT COUNT(*) FROM icd_index where icd = '25000'吗? -
同样的结果。我第一次执行它是 70 秒。如果我重新执行它,它是瞬时的(大概来自缓存)。如果我重置缓存并运行它,它是 0.7 秒。我正在使用 MySQL 5.6,以防万一。
-
您尝试过不同的存储引擎吗? MyISAM 已经过时了,我不知道它是否可以利用这些天可用的所有硬件。
-
我最初是从 InnoDB 开始的。但是在 InnoDB 中计算整个表的速度非常慢,所以我切换到了 MyISAM。我不需要事务,因为这个数据库是只读的——数据是固定的,永远不会改变。但如果切换到 InnoDB 会有所帮助,我会考虑(尽管这样做需要花费数小时的时间......)另外,我在查询中添加了说明,以防有帮助
-
InnoDB必须配置为快速。您可以选择将多少 RAM 专用于 InnoDB,并使用它来存储它在那里使用的数据。可以从 RAM 而不是磁盘访问的 6500 万行是非常非常快速的操作。魔术变量称为innodb_buffer_pool_size。另外,还有TokuDB,另一个出色的存储引擎。另外,您使用的是机械硬盘还是 SSD?