agi*_*DBA 4 mysql innodb index primary-key
我有一个表(InnoDB),数据长度约为 36G,索引长度为 23G。
它有一个跨三列的复合主键。
作为减小此表大小的初步尝试,我删除了主键(实际上并不需要)。然而,数据长度和索引长度是相同的。
这是意料之中的吗?
在此数据库上启用UPDATE innodb_file_per_table
更新
mysql> show create table event;
CREATE TABLE `event` (
`owner_id` varchar(36) NOT NULL,
`key_id` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
KEY `owner_id_idx` (`owner_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8
Run Code Online (Sandbox Code Playgroud)
恰恰相反:表的大小会影响主键的大小。因此,是的,这是意料之中的。
主键位于gen_clust_index 中,也就是聚集索引。
聚集索引如何加快查询速度
通过聚集索引访问一行很快,因为行数据位于索引搜索引导的同一页上。如果表很大,与使用与索引记录不同的页面存储行数据的存储组织相比,聚簇索引体系结构通常可以节省磁盘 I/O 操作。(例如,MyISAM 将一个文件用于数据行,另一个用于索引记录。)
根据这个描述,InnoDB 存储引擎的每一行都位于聚集索引内。
有鉴于此,有两个问题需要回答:
这两个问题的答案只有一个。聚集索引上的 MySQL 文档说:
如果 table 没有 PRIMARY KEY 或合适的 UNIQUE 索引,则 InnoDB 在包含行 ID 值的合成列上内部生成隐藏的聚集索引。行按 InnoDB 分配给此类表中行的 ID 排序。行 ID 是一个 6 字节的字段,随着插入新行而单调增加。因此,按行 ID 排序的行在物理上是按插入顺序排列的。
OPTIMIZE TABLE由于您没有尝试删除任何行,因此变得无效。由于您没有删除任何行,因此行占用的所有空间仍将位于聚集索引内。您只是将一个键(您的主键)换成了另一个(6 字节的行 ID)。我有您可能需要执行的三 (3) 项技术之一
INTs到 SMALLINT 或 TINYINTVARCHAR(255)到VARCHAR(128)在应用这三 (3) 种技术之一之前,请备份您的表。
一旦您应用了这三 (3) 项技术之一,您就可以执行以下操作之一来缩小聚集索引(例如,mydb.mytable):
OPTIMIZE TABLE mydb.mytable;ALTER TABLE mydb.mytable ENGINE=InnoDB;这是你的最后一条评论
因此,如果原始主键大于 6 字节,我是否不希望看到聚集索引大小减少?
即使PRIMARY KEY是 now CHAR(255),每一行都位于聚集索引内。InnoDB 中的每个页面都是 16K。6 字节的行 ID(InnoDB 仍然在内部使用)仍然嵌入在相同的页面中。丢弃PRIMARY KEY比物理丢弃更像是一种逻辑丢弃。这就是为什么我之前说
您只是将一个键(您的主键)换成了另一个(6 字节的行 ID)
删除 的物理行为PRIMARY KEY可能需要在逻辑删除(标记)每一行中跑到每一行,而不是使用某些内部列组合,PRIMARY KEY而是恢复到行 ID。这几乎不会改变 16K InnoDB 页面的使用,无论行长度是长(可能允许页面内有几行)还是短(可能允许页面内有更多行)。
运行OPTIMIZE TABLE缩小它仍然不会产生任何明显的变化,因为聚集索引的标记机制仍然存在。给定表中行的平均长度,完全相同的行数使聚集索引保持相同的大小。
查看我之前提到的三种技术和集群索引上的 MySQL 文档。给定表中的行数和您当前的表定义,如果您无法减小列大小、删除列、删除行并将它们归档到其他地方,那么您将无法缩小表。
| 归档时间: |
|
| 查看次数: |
5623 次 |
| 最近记录: |