Sid*_*rma 5 mysql database database-design
我有一个托管在 Google Cloud SQL 上的 MySQL 表,其中包含超过 10 亿行。
>> SHOW CREATE TABLE depth
CREATE TABLE `depth` (
`date` date DEFAULT NULL,
`receive_time` datetime(3) DEFAULT NULL,
`instrument_token` bigint(20) unsigned DEFAULT NULL,
`level` tinyint(3) unsigned DEFAULT NULL,
`bid_count` smallint(5) unsigned DEFAULT NULL,
`bid_size` bigint(20) unsigned DEFAULT NULL,
`bid_price` float DEFAULT NULL,
`ask_price` float DEFAULT NULL,
`ask_size` bigint(20) unsigned DEFAULT NULL,
`ask_count` smallint(5) unsigned DEFAULT NULL,
KEY `date_time_sym` (`date`,`receive_time`,`instrument_token`),
KEY `date_sym_time` (`date`,`instrument_token`,`receive_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)
为了获取数据和索引大小,我运行查询
SHOW TABLE STATUS from mktdata where Name = "depth";
Run Code Online (Sandbox Code Playgroud)
在这里,我得到一个包含一行的表输出,其中一些重要字段的值如下:
Name: depth
Engine:InnoDB
Version:10
Row_format:Dynamic
Rows: 1,72,08,21,447
Avg_row_length: 78
Index_length: 1,83,90,03,07,456
Data_length: 1,35,24,53,32,480
Run Code Online (Sandbox Code Playgroud)
问题:为什么Index_length大于Data_length?你可以在上面看到我的索引,为什么它们需要这么多空间来存储?我不太了解索引是如何创建和存储的,所以请从基础知识开始解释。
小智 8
这可能会发生。
您有一个索引较多的表。这可能有用也可能没用。
以下是一些常见错误:
“我正在对所有列建立索引”——通常没有用。
“我对我使用的每一列都建立了索引”——但未能理解“复合”索引的重要性:INDEX(last,first) 与 INDEX(last), INDEX(first)
INDEX(a)、INDEX(a,b)——没有意识到第一个是多余的。
PRIMARY KEY(id), INDEX(id)——没有意识到 PRIMARY KEY 是一个 INDEX(和 UNIQUE)。
显示创建表并描述主要选择。然后我们可以讨论哪些索引是最佳的,哪些可以删除。
进一步说明:INDEX 包含表中每一行的一行,并包含索引列,以及指向 DATA 中的行的指针。如果有多个索引,它们都包含在 INDEX_LENGTH 中(InnoDB 的 PRIMARY KEY 除外)。
或者,可能是您的最佳索引集,并且索引大小大于数据。
参考链接:https://forums.mysql.com/read.php?10,390235,390352
Index_length > Data_length 的情况很少见,但也不是“坏”或“错误”。
您没有显式的PRIMARY KEY,因此它是一个隐藏的 6 字节字段,其工作原理有点像 auto_increment。
每个辅助密钥都包含 PK 的副本。
Avg_row_length: 78Date_length-- 由/计算得出Rows。 不过,Rows只是一个估计。我发现它相差两倍或更多。
您声明的每一列都是NULLable;这是故意的吗?大多数不应该是吗NOT NULL?以下计算未考虑列可以是NULL。
但是,如果有很多值NULL,则可能 78 字节/行是有效的。例如, aBIGINT通常需要 8 个字节(加上开销),但如果NULL,则需要 0 个字节(加上开销)。
1 索引大小:
(20)无关紧要)总共 24 个字节。
这相当于每行 64 字节。*172 万行 = 110GB。
由于有 2 个索引,所以要加倍——220GB。`显示表状态显示 184GB。这两个数字足够接近。(我使用的一些数字只是近似值。)
没有明确的说明是很顽皮的PRIMARY KEY。使用 anAUTO_INCREMENT会导致 4 字节空间不足INT或使用巨大的 8 字节空间BIGINT。如果某些列的组合是唯一的,那么它们可能是 PK。这样做可能会缩小数据大小(通过 gettring 消除 6 字节 PK),并且可能会缩小索引(如果 3 个索引列中的任何一个是 PK 的一部分)。
有关索引的更多信息: http://mysql.rjweb.org/doc.php/index_cookbook_mysql 请注意它关于“范围”和索引的内容。date如果您在或上使用范围receive_time,则您拥有的索引将不是最佳的。