Mysql INFORMATION_SCHEMA.INNODB_BUFFER_页面和INFORMATION_SCHEMA.TABLES中的不同数据大小
我试图了解表是否正在加载到InnoDB缓冲区。为此,我正在查询信息\u SCHEMA.INNODB\u BUFFER\u PAGE表。 据我所见,这张桌子已经满了。然而,加载到缓冲区中的数据量(MB)与INFORMATION_SCHEMA.TABLES中显示的数据量大不相同 例如:Mysql INFORMATION_SCHEMA.INNODB_BUFFER_页面和INFORMATION_SCHEMA.TABLES中的不同数据大小,mysql,database-performance,amazon-aurora,Mysql,Database Performance,Amazon Aurora,我试图了解表是否正在加载到InnoDB缓冲区。为此,我正在查询信息\u SCHEMA.INNODB\u BUFFER\u PAGE表。 据我所见,这张桌子已经满了。然而,加载到缓冲区中的数据量(MB)与INFORMATION_SCHEMA.TABLES中显示的数据量大不相同 例如: SELECT TABLE_NAME, TABLE_ROWS , CAST(DATA_LENGTH/POWER(1024,2) AS DECIMAL(5, 0)) AS DATA_LENGTH_MB ,
SELECT TABLE_NAME, TABLE_ROWS
, CAST(DATA_LENGTH/POWER(1024,2) AS DECIMAL(5, 0)) AS DATA_LENGTH_MB
, CAST(DATA_FREE/POWER(1024,2) AS DECIMAL(5, 0)) AS DATA_FREE_MB
FROM INFORMATION_SCHEMA.TABLES
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = '<db_name>'
AND TABLE_NAME = '<table_name>';
| TABLE_NAME | TABLE_ROWS | DATA_LENGTH_MB | DATA_FREE_MB |
|-----------------------------------------------------------|
| <table_name> | 39735968 | 10516 | 548 |
INNODB_BUFFER_PAGE表中的信息模式包含有关缓冲池中页面的信息
注意最后4个单词
这表明INNODB\u BUFFER\u PAGE
的总和可能小于从INFORMATION\u SCHEMA.TABLES
获得的总和
(我不知道所有细节,但这里有一些一般性陈述。)
缓冲池可能包含:
- 表的部分或全部叶节点
- 表的部分或所有非叶节点
- 表的每个非主索引的叶节点和非叶节点同上
- 更多表格同上
- 文本和BLOB(以及大的VARCHAR)可能会记录在案。这大大增加了占用的磁盘空间。但我认为你的情况不会发生这种情况。但是,请参见下文
- 缓冲池的25%(可调)保留给“更改缓冲区”;这是一种用于更改辅助索引的写缓存
- 其他东西
- 缓冲池的百分之几被保留或因其他原因丢失
- 预先分配的块(可能反映在无数据中)
- 未填充的块(可能没有数据或索引块是100%满的)
- 事务会产生额外的行拷贝——这些行在undo/redo空间或数据块中来来去去去
- 块分割
- 等等
- 经验法则是数据占用的磁盘空间(数据长度)是预测大小的2-3倍。(“Predicted”=将单个数据大小相加,例如每个
加上4个字节)INT
varchar
都存储在记录外。数学几乎算出来了
让我们一起探讨两种思考方式
SELECT count(*),
AVG(LENGTH(col3)) AS avg3,
AVG(LENGTH(col5)) AS avg5,
... -- the rest of the VARCHARs
FROM table_name;
(我特别想要
LENGTH()
,而不是CHAR\u LENGTH()
)抱歉耽搁了这么久。我终于设法确认,事实上有一个数据清理正在讨论的表上执行。大约60%的记录被删除。
这应该可以解释mysql.innodb\u index\u stats表中size和n\u leaf\u pages值之间的差异。不确定这是不是正常行为
所以来回答我的问题。要估计表在InnoDB池中的容量,我可能需要查看mysql.InnoDB_index_statssize而不是INFORMATION_SCHEMA.table
SELECT TABLE_NAME, ROUND((stat_value*@@innodb_page_size)/POWER(1024,2)) AS DATA_SIZE_MB
FROM mysql.innodb_index_stats
WHERE database_name = 'db_name' AND index_name = 'PRIMARY' AND table_name = 'table_name'
AND stat_name = 'n_leaf_pages';
感谢@Rick James帮助我完成此任务请提供
SHOW CREATE TABLE
。特别是,我想知道是否有TEXT
或BLOB
列。从选择p.TABLE\u名称、p.INDEX\u名称、页面类型、页面状态、四舍五入(SUM(DATA\u SIZE)/POWER(1024,2))作为数据大小\u MB、SUM(NUMBER\u记录)中可以得到什么AS NUMBER_记录来自信息_SCHEMA.INNODB_BUFFER_页面作为p,其中p.TABLE_名称(如“…”)按1,2,3,4的顺序按p.TABLE_名称、p.INDEX_名称分组;创建附在上面的TABKE语句。没有BLOB或文本列您的语句的输出:TABLE|U NAME | INDEX|U NAME | page|U type | page|U state | DATA|U SIZE | MB | NUMBER|记录------------------------------------------------------------------------------------------主索引|文件| page | 1461 | 19111932看起来大约有50%的te表被删除了自上次以来,极光有一些显著的差异;我不知道它们是否相关。num行的变化并不让我担心,但“3.5GB对10.5GB”似乎非常重要(我的答案中没有任何东西可以解释,即使是挥手)。这些varchar的平均大小是多少?一行的最大值不超过2K,即使假设在整个过程中使用3字节utf8字符——总共90GB。我猜一行通常总共是350字节16GB。(这假设大部分是1字节字符,而varchar不是很满。)因此,您的10.5GB很接近,但3.5GB意味着您的varchar非常空,或者3.5非常低。嗯,我原以为完全加载到内存中的表的数字会非常接近。但现在它大约是磁盘上表大小的30%到60%。我的最终目标是估计有多少表可以加载到内存中。但考虑到数字如此之多,目前我看不出有什么办法可以做到这一点different@RimvydasGurskis-我在回答时又挥了挥手。祝你好运请在此处或以某种形式的博客发布您的发现。ROW|u FORMAT=DynamicHere是平均值:count(*)col3 | col5 | col8 | col11 | col18 47074590 | 6.0000 | 22.3948 | 11.0000 |(null)| 7.2727给定当前大小(3.8 GB)平均行长度约为80字节。这是有道理的,因为大约有一半的列AllowNullSnumbers是mysql。innodb_index_统计数据在我看来很奇怪。大小和n_leaf_pages值之间存在很大差异。选择stat_name、stat_value、ROUND((stat_value*@@innodb_page_size)/POWER(1024,2))作为mysql.innodb_index_stats中的数据_size_MB,其中数据库_name='db_name'和索引_name='PRIMARY'
SELECT COUNT(1) FROM <db_name>.<table_name>;
44947428
CREATE TABLE `table_name` (
`recid` BINARY(32) NOT NULL,
`col1` INT(11) UNSIGNED NOT NULL,
`col2` TINYINT(1) UNSIGNED NOT NULL,
`col3` VARCHAR(250) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col4` TINYINT(1) UNSIGNED NOT NULL,
`col5` VARCHAR(250) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col6` TINYINT(1) UNSIGNED NOT NULL,
`col7` TINYINT(1) UNSIGNED NOT NULL,
`col8` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col9` TINYINT(1) UNSIGNED NOT NULL,
`col10` TINYINT(1) UNSIGNED NOT NULL,
`col11` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col12` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0',
`col13` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1',
`col14` INT(11) UNSIGNED NULL DEFAULT NULL,
`col15` BINARY(32) NULL DEFAULT NULL,
`col16` CHAR(2) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col17` TINYINT(1) NULL DEFAULT NULL,
`col18` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`col19` TINYINT(1) NULL DEFAULT NULL,
`col20` TINYINT(1) NULL DEFAULT NULL,
PRIMARY KEY (`recid`) USING BTREE,
UNIQUE INDEX `col3` (`col3`) USING BTREE,
INDEX `col5` (`col5`) USING BTREE,
INDEX `col8` (`col8`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
SELECT count(*),
AVG(LENGTH(col3)) AS avg3,
AVG(LENGTH(col5)) AS avg5,
... -- the rest of the VARCHARs
FROM table_name;
SELECT TABLE_NAME, ROUND((stat_value*@@innodb_page_size)/POWER(1024,2)) AS DATA_SIZE_MB
FROM mysql.innodb_index_stats
WHERE database_name = 'db_name' AND index_name = 'PRIMARY' AND table_name = 'table_name'
AND stat_name = 'n_leaf_pages';