在4,000多万行表上为几个不同的查询创建索引

时间:2017-03-27 20:06:30

标签: mysql indexing

该表目前是一个400万(~50 GB)的行表并且正在快速增长。

我们不希望包含EndTime无效且因此少于StartTime的任何行,因为它至少有1,000行,它们为零。

我的问题是什么样的索引最适合这三个查询? 我猜可能是一个首先是EndTime和StartTime第二的复合索引?

StartTime和EndTime字段都包含unix时间戳,如:1401951888

SELECT AVG(EndTime-StartTime) FROM sessions WHERE EndTime>StartTime;
SELECT MAX(EndTime-StartTime) FROM sessions WHERE EndTime>StartTime;
SELECT MIN(EndTime-StartTime) FROM sessions WHERE EndTime>StartTime;
+----------------------+------------+------+-----+---------+-------+
| Field                | Type       | Null | Key | Default | Extra |
+----------------------+------------+------+-----+---------+-------+
| Uuid                 | char(36)   | NO   | PRI | NULL    |       |
| StartTime            | int(11)    | YES  |     | NULL    |       |
| EndTime              | int(11)    | YES  |     | NULL    |       |
+----------------------+------------+------+-----+---------+-------+

1 个答案:

答案 0 :(得分:4)

  

该表目前是一个400万(~50 GB)的行表并且正在快速增长。

只有3列的4M行,它的50GB?哇......某处有问题吗?

  

我们不希望包含EndTime无效且因此少于StartTime的任何行,因为它至少有1,000行,而且它们为零。

由于没有其他条件,查询将必须处理整个表,减去1000行。因此,任何指数都将毫无用处。

除非表中的列数多于您显示的列数,否则索引的唯一用途将比磁盘表小得多,因此扫描速度要快得多。

现在,在MySQL的最新版本中,您现在可以在虚拟列上创建functional indexes!因此,您可以在:

上创建索引
endTime - startTime

如果你的max()和min()使用索引,它们将是瞬时的,因为在有序集合中找到min / max是一个O(1)操作,只需要查看第一个或最后一个条目。但是,您的avg()当然必须检查所有行以计算平均值。