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
--两次,mobile
和 date
。
我有那两个 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
--两次,mobile
和 date
。