我已经创建了下面列出的测量表。 该表会定期写入,几天后会迅速增长到包含数百万行。 阅读时:我只需要测量的精确时间及其值(unix_epoch 和值)。
为了提高性能,我添加了 date_from_epoch 列,这是从 unix_epoch(测量精确时间)中提取的日期,格式为:yyyymmdd。它应该具有良好的选择性(在将多天的测量值写入表中之后)并且我将其用作索引的键。我希望只扫描我想要读取测量值的日子,而不是表中出现的所有日子(例如:10 天后,如果每天添加 1,000,000,我希望只扫描 1,000,000 行,如果我需要一天内包含的数据,而不是 10,000,000 个)。
我还有:
- 使用 innoDB 作为引擎
- 通过散列将表分成 10 个文件以帮助 I/O
- 确保我的查询中使用的类型与列类型相同(或者我的验证有误?)。
问题: 测量值在测量表中滴落 2 天后,我进行了测试。 使用 EXPLAIN,我发现我的读取查询没有使用索引。为什么查询没有使用索引?
表是用以下方法创建的:
CREATE TABLE measurements(
date_from_epoch INT UNSIGNED,
unix_epoch INT UNSIGNED,
application_name varchar(255),
environment varchar(255),
metric_name varchar(255),
host_name varchar(1024),
value FLOAT(38,3)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY HASH(unix_epoch)
PARTITIONS 10;
CREATE TRIGGER write_epoch_day
BEFORE INSERT ON measurements
FOR EACH ROW
SET NEW.date_from_epoch = FROM_UNIXTIME(NEW.unix_epoch, '%Y%m%d');
ALTER TABLE measurements ADD INDEX (date_from_epoch);
查询是:
EXPLAIN SELECT * FROM measurements
WHERE date_from_epoch >= 20150615 AND date_from_epoch <= 20150615
AND unix_epoch >= 1434423478 AND unix_epoch <= 1434430678
AND BINARY application_name = 'all'
AND BINARY environment = 'prod'
AND BINARY metric_name = 'Internet availability'
AND (BINARY host_name = 'kitkat' )
ORDER BY unix_epoch ASC;
解释给出:
id select_type table type possible_keys key key_len ref rows Extra
-------------------------------------------------------------------------------------------------------------------------------------------------------
1 SIMPLE measurements ALL date_from_epoch 118011 Using where; Using filesort
感谢阅读和挠头!
最佳答案
在 MYSQL 中有一个使用 FORCE INDEX
的选项
引用this以便更好地理解。
关于MySQL 不使用带有选择性 INT 键的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30859487/