编辑 1:
似乎将主键从
PRIMARY KEY (`tm_stamp`,`fk_channel`)
至
PRIMARY KEY (`fk_channel`,`tm_stamp`)
对于 MyISAM 和 InnoDB 来说总是有意义的。请参阅http://sqlfiddle.com/#!2/0aa08/1以证明确实如此。
原答案:
判断是否改变
PRIMARY KEY (`tm_stamp`,`fk_channel`)
至
PRIMARY KEY (`fk_channel`,`tm_stamp`)
会提高查询的性能,您需要确定哪个字段的值基数更高(哪个字段的值更多样化)。跑步
SELECT COUNT(DISTINCT tm_stamp), COUNT(DISTINCT fk_channel) FROM measurements;
会给你列的基数。
因此,要正确回答您的问题,我们首先需要知道: 和 之间的常见值范围是B
什么C
?60?3,600?86,400?更多的?
例如,假设
SELECT COUNT(DISTINCT tm_stamp), COUNT(DISTINCT fk_channel) FROM measurements;
返回 32,768 和 256。32,768 除以 256 是 128。这告诉我们tm_stamp
对于 的每个值都有 128 个唯一值fk_channel
。
所以如果和之间的差值B
通常C
小于128,那么就留下tm_stamp
作为主键中的第一个字段。如果 128 或更大,则创建fk_channel
第一个字段。
另一个问题:是否fk_channel
需要是一个INT
(40 亿个唯一值,其中一半是负数)?如果没有,那么更改fk_channel
为TINYINT UNSIGNED
(如果您有 256 个唯一值)或SMALLINT UNSIGNED
(65536 个唯一值)将节省大量时间和空间。
例如,假设您有 256 个最大可能fk_channel
值和 65,536 个可能值value
,那么您可以通过以下方式更改架构:
create table measurements_new (
tm_stamp INT UNSIGNED NOT NULL DEFAULT '0',
fk_channel TINYINT UNSIGNED NOT NULL DEFAULT '0', -- remove UNSIGNED if values can be negative
value SMALLINT UNSIGNED DEFAULT NULL, -- remove UNSIGNED if values can be negative
PRIMARY KEY (tm_stamp,fk_channel)
) ENGINE=InnoDB
SELECT
tm_stamp,
fk_channel,
value
FROM
measurements
ORDER BY
tm_stamp,
fk_channel;
RENAME TABLE measurements TO measurements_old, measurements_new TO measurements;
这会将现有数据按顺序存储在新表中PRIMARY KEY
,这将在一定程度上提高性能。