我有两个表架构:
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;
到目前为止,每张桌子都有 4,000,000 记录, 所以我正在尝试构建最合适的架构,这种架构更快,占用更少的存储空间。
当我检查Table
中每个MySql Workbeanch
的状态时,我感到很困惑:
第一张表:
第二张表
当我将IDX_Datee
密钥从Index
更改为Primary
时,它不占用任何空间。
我相信第二种模式对我来说更好,但我对这种差异没有很好的理解。
请问任何人解释一下吗?
答案 0 :(得分:2)
该表是索引组织的。数据记录按索引顺序存储。 见https://dev.mysql.com/doc/refman/5.5/en/optimizing-primary-keys.html
"使用InnoDB存储引擎,表格数据在物理上进行组织,以根据主键列或列进行超快速查找和排序"
所以不需要额外的索引
答案 1 :(得分:1)
PK 指定的单行上的所有操作(选择,插入,删除,更新)将非常快速有效。深入了解包含数据的BTree,并由PK组织,并且有一行可以使用。
PK需要占用少量空间,就像任何BTree都超过叶节点一样。作为一个经验法则,MySQL的BTrees(数据或索引)具有大约100的扇出。也就是说,每个节点下面有大约100个节点。这意味着对于PK开销的“其余”非叶节点只有大约1%的开销。
16KB / 61约为268 - 你的“扇出”。
对于初学者,我建议DOUBLE
(8字节)对于纬度和经度来说是过度杀伤力,除非你试图将一只跳蚤与另一只跳蚤区分开来。这是lat / lng的表示选择的my table。
INT
是4个字节。如果您确定不会超过1600万,请将PK更改为MEDIUMINT UNSIGNED
(3个字节)。 (我认为这太冒险了。)
PK的大小非常重要,因为它包含在每个辅助密钥中。
如果(mobile, date)
是唯一的,它也可能是PK。这样可以减少id
,和的两个副本,从而加快基于mobile
的查询。
如果mobile
包含电话号码,则有些号码不适合。最好使用DECIMAL(11)
需要5个字节; (13)
需要6.如果相反,mobile
在某个其他表中是AUTO_INCREMENT
,则可能是SMALLINT UNSIGNED
(每个表每个副本2个字节 )会更好。
您的第一个表有4个额外列(相对于第二个表):id
- 两次,mobile
和date
。