我在mysql 5.6.10实例上有一个非常大的表(大约4.8亿行)。
存储引擎是InnoDB。 (表和数据库默认值)。
该表通过merchantId(bigint:一种客户端标识符)的散列进行分区,该查询在与单个商家相关的查询时提供帮助。由于查询跨越多个商家时性能显着下降,我决定在ACTION_DATE(活动发生的DATE)按范围对表进行重新分区。认为我很聪明,我决定添加一些(5)新字段供将来使用(unused_varchar1 varchar(200)等),因为表格太大,添加新字段本质上需要重建,所以为什么不呢? ...
我将新表结构创建为_new,使用mysql dump将现有文件转储到辅助服务器。然后我使用awk脚本来熟化名称和一些其他细节以适应新表(将tableName更改为tableName_new),并开始加载。
现有表约为430 GB。文本文件类似地约为403 GB。因此我感到惊讶的是,新桌子最终占用了大约840 GB! (基于.ibd文件的linux fize大小)
所以,我有2个基本问题,这些问题实际上就是为什么以及现在......
我认为新表更大,因为转储文件是前一个分区(merchantId)的顺序,而负载插入到新分区(活动日期)中,创建了一个半随机的插入顺序。随机性导致mysql在页面中留下足够的空间(大约50%)以供将来插入。 (我对这里的术语有点模糊,在我的职业生涯中花了更多的时间在Sql Server DB而不是MySql Dbs ......)我无法在mysql中找到任何内部统计信息,每页空间无空间。 INFORMATION_SCHEMA.TABLES DATA_FREE统计数据令人难以置信68MB。
如果有帮助,这些是来自I_S.TABLES的相关统计数据:
TABLE_TYPE:BASE TABLE
发动机:InnoDB
版本:10
ROW_FORMAT:紧凑型
TABLE_ROWS:488,094,271
AVG_ROW_LENGTH:1,564
DATA_LENGTH:763,509,358,592(711 GB)
INDEX_LENGTH:100,065,574,912(93.19 GB)
DATA_FREE:68,157,440(0.06 GB)
我意识到这不会增加到840 GB,但正如我所说,这是.ibd文件的大小,似乎与I_S.TABLES统计数据略有不同。无论哪种方式,它都远远超过文本转储文件。
我离题了......
我的问题是我的理论是否重新解释是否解释了大致翻了一倍的规模。还是有另一种解释?我认为额外的列(2 Bigint,2 Varchar(200),1 Date)不是罪魁祸首,因为它们都是空的。我的餐巾纸计算是附加列将添加< 9 GB。同样,UID上的一个附加索引应该是一个相对较小的附加值。
后续问题是如果我想尝试压缩表格,我现在可以做什么。 (服务器现在只有大约385 GB免费...)
如果我重复这个过程,转储到文件,重新加载,这次是按照当前的分区顺序,我最终会得到一个更像原始表大小的表~430 GB?
以下是DDL的相关部分。
旧表:
CREATE TABLE table_name (
`AUTO_SEQ` bigint(20) NOT NULL,
`MERCHANT_ID` bigint(20) NOT NULL,
`AFFILIATE_ID` bigint(20) DEFAULT NULL,
`PROGRAM_ID` bigint(20) NOT NULL,
`ACTION_DATE` date DEFAULT NULL,
`UID` varchar(128) DEFAULT NULL,
... additional columns ...
PRIMARY KEY (`AUTO_SEQ`,`MERCHANT_ID`,`PROGRAM_ID`),
KEY `oc_rpt_mpad_idx` (`MERCHANT_ID`,`PROGRAM_ID`,`ACTION_DATE`,`AFFILIATE_ID`),
KEY `oc_rpt_mapd` (`MERCHANT_ID`,`ACTION_DATE`),
KEY `oc_rpt_apda_idx` (`AFFILIATE_ID`,`PROGRAM_ID`,`ACTION_DATE`,`MERCHANT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (merchant_id)
PARTITIONS 16 */
新表:
CREATE TABLE `tableName_new` (
`AUTO_SEQ` bigint(20) NOT NULL,
`MERCHANT_ID` bigint(20) NOT NULL,
`AFFILIATE_ID` bigint(20) DEFAULT NULL,
`PROGRAM_ID` bigint(20) NOT NULL,
`ACTION_DATE` date NOT NULL DEFAULT '0000-00-00',
`UID` varchar(128) DEFAULT NULL,
... additional columns...
# NEW COLUMNS (ALL NULL)
`UNUSED_BIGINT1` bigint(20) DEFAULT NULL,
`UNUSED_BIGINT2` bigint(20) DEFAULT NULL,
`UNUSED_VARCHAR1` varchar(200) DEFAULT NULL,
`UNUSED_VARCHAR2` varchar(200) DEFAULT NULL,
`UNUSED_DATE1` date DEFAULT NULL,
PRIMARY KEY (`AUTO_SEQ`,`ACTION_DATE`),
KEY `oc_rpt_mpad_idx` (`MERCHANT_ID`,`PROGRAM_ID`,`ACTION_DATE`,`AFFILIATE_ID`),
KEY `oc_rpt_mapd` (`ACTION_DATE`),
KEY `oc_rpt_apda_idx` (`AFFILIATE_ID`,`PROGRAM_ID`,`ACTION_DATE`,`MERCHANT_ID`),
KEY `oc_uid` (`UID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50500 PARTITION BY RANGE COLUMNS(ACTION_DATE)
(PARTITION p01 VALUES LESS THAN ('2012-01-01') ENGINE = InnoDB,
PARTITION p02 VALUES LESS THAN ('2012-04-01') ENGINE = InnoDB,
PARTITION p03 VALUES LESS THAN ('2012-07-01') ENGINE = InnoDB,
PARTITION p04 VALUES LESS THAN ('2012-10-01') ENGINE = InnoDB,
PARTITION p05 VALUES LESS THAN ('2013-01-01') ENGINE = InnoDB,
PARTITION p06 VALUES LESS THAN ('2013-04-01') ENGINE = InnoDB,
PARTITION p07 VALUES LESS THAN ('2013-07-01') ENGINE = InnoDB,
PARTITION p08 VALUES LESS THAN ('2013-10-01') ENGINE = InnoDB,
PARTITION p09 VALUES LESS THAN ('2014-01-01') ENGINE = InnoDB,
PARTITION p10 VALUES LESS THAN ('2014-04-01') ENGINE = InnoDB,
PARTITION p11 VALUES LESS THAN ('2014-07-01') ENGINE = InnoDB,
PARTITION p12 VALUES LESS THAN ('2014-10-01') ENGINE = InnoDB,
PARTITION p13 VALUES LESS THAN ('2015-01-01') ENGINE = InnoDB,
PARTITION p14 VALUES LESS THAN ('2015-04-01') ENGINE = InnoDB,
PARTITION p15 VALUES LESS THAN ('2015-07-01') ENGINE = InnoDB,
PARTITION p16 VALUES LESS THAN ('2015-10-01') ENGINE = InnoDB,
PARTITION p17 VALUES LESS THAN ('2016-01-01') ENGINE = InnoDB,
PARTITION p18 VALUES LESS THAN ('2016-04-01') ENGINE = InnoDB,
PARTITION p19 VALUES LESS THAN ('2016-07-01') ENGINE = InnoDB,
PARTITION p20 VALUES LESS THAN ('2016-10-01') ENGINE = InnoDB,
PARTITION p21 VALUES LESS THAN ('2017-01-01') ENGINE = InnoDB,
PARTITION p22 VALUES LESS THAN ('2017-04-01') ENGINE = InnoDB,
PARTITION p23 VALUES LESS THAN ('2017-07-01') ENGINE = InnoDB,
PARTITION p24 VALUES LESS THAN ('2017-10-01') ENGINE = InnoDB,
PARTITION p25 VALUES LESS THAN ('2018-01-01') ENGINE = InnoDB,
PARTITION p26 VALUES LESS THAN ('2018-04-01') ENGINE = InnoDB,
PARTITION p27 VALUES LESS THAN ('2018-07-01') ENGINE = InnoDB,
PARTITION p28 VALUES LESS THAN ('2018-10-01') ENGINE = InnoDB,
PARTITION p29 VALUES LESS THAN ('2019-01-01') ENGINE = InnoDB,
PARTITION p30 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB) */
















