MySql 主键不消耗任何大小

MySql primary key doesn't consume any size

我有那两个 tables 模式:

CREATE TABLE `myTable` (
  id int(11) NOT NULL AUTO_INCREMENT,
  lat double NOT NULL,
  lng double NOT NULL,
  date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  mobile bigint(11) unsigned NOT NULL,
  date_updated datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  PRIMARY KEY (`id`),
  KEY `IDX_Datee` (`mobile`,`date`),
  CONSTRAINT `FK_DeviceLocationss` FOREIGN KEY (`mobile`) REFERENCES `device` (`serial`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

这是第二个:

CREATE TABLE `myTable2` (
  lat double NOT NULL,
  lng double NOT NULL,
  date datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  mobile bigint(11) unsigned NOT NULL,
  date_updated datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  PRIMARY KEY `IDX_Datee2` (`mobile`,`date`),
  CONSTRAINT `FK_DeviceLocationss2` FOREIGN KEY (`mobile`) REFERENCES `device` (`serial`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

在每个 table 中,到目前为止大约有 4,000,000 条记录, 所以我正在尝试构建速度更快、存储消耗更少的最 suitable 模式。

当我检查 MySql Workbeanch 中每个 Table 的状态时,我有点困惑:

第一个Table:

第二个Table

当我将 IDX_Datee 键从 Index 更改为 Primary 时,它不会消耗任何 space。

我认为第二种模式更适合我,但我不太了解这种差异。

谁能解释一下?

table 是索引组织的。数据记录按索引顺序存储。 见 https://dev.mysql.com/doc/refman/5.5/en/optimizing-primary-keys.html

"With the InnoDB storage engine, the table data is physically organized to do ultra-fast lookups and sorts based on the primary key column or columns"

所以不需要额外的索引

PK指定单个行上的所有操作(select、插入、删除、更新)将是非常快速和高效。向下钻取包含数据并由 PK 组织的 BTree,并且有要处理的行。

PK 只需要很少的 space,就像任何 BTree 都比叶节点多一样。根据经验,MySQL 的 BTree(数据或索引)的扇出约为 100。也就是说,每个节点下有大约 100 个节点。这意味着对于 'rest' 的 PK 开销,非叶节点只有大约 1% 的开销。

16KB / 61 大约是 268 -- 你的 "fanout".

对于初学者,我建议 DOUBLE(8 字节)对于纬度和经度来说是大材小用,除非您试图区分狗身上的一只跳蚤和另一只跳蚤。这是 lat/lng 的 my table 表示选择。

INT 是 4 个字节。如果您确定不会超过 1600 万,请将 PK 更改为 MEDIUMINT UNSIGNED(3 个字节)。 (我建议这样做太冒险了。)

PK 的大小非常重要,因为它包含在每个辅助密钥中。

如果(mobile, date)是唯一的,那么它也可能是PK。这削减了两个副本id加速了基于mobile.

的查询

如果 mobile 包含 phone 个数字,那么有些数字将不适合。最好使用 DECIMAL(11) 占用 5 个字节; (13) 占用 6。 相反,如果 mobile 在其他 table 中是一个 AUTO_INCREMENT,甚至 SMALLINT UNSIGNED(2 个字节 per复制,根据 table) 会更好。

您的第一个 table 有 4 个额外的列(相对于第二个 table):id--两次,mobiledate