Mysql 为什么这些桌子都一样大?

Mysql 为什么这些桌子都一样大?,mysql,sql,Mysql,Sql,我正试图测量TINYINT和INT之间的差异,突然发现了一些有趣的东西。对于列数较少的表,数据类型的选择似乎不会影响表的大小 服务器版本:5.1.41-3ubuntu12.10(Ubuntu) 例如: mysql> describe tinyint_test; +----------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-

我正试图测量TINYINT和INT之间的差异,突然发现了一些有趣的东西。对于列数较少的表,数据类型的选择似乎不会影响表的大小

服务器版本:5.1.41-3ubuntu12.10(Ubuntu)

例如:

mysql> describe tinyint_test;
+----------+------------+------+-----+---------+-------+
| Field    | Type       | Null | Key | Default | Extra |
+----------+------------+------+-----+---------+-------+
| id       | int(11)    | YES  |     | NULL    |       |
| test_int | tinyint(4) | YES  |     | NULL    |       |
+----------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> describe tinyint_id_test;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | tinyint(4) | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> describe int_test;
+--------+---------+------+-----+---------+-------+
| Field  | Type    | Null | Key | Default | Extra |
+--------+---------+------+-----+---------+-------+
| not_id | int(11) | YES  |     | NULL    |       |
+--------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> select * from tinyint_test;
+------+----------+
| id   | test_int |
+------+----------+
|    1 |        1 |
|    2 |        2 |
|    3 |      127 |
|   10 |       50 |
+------+----------+
4 rows in set (0.00 sec)

mysql> select * from tinyint_id_test;
+------+
| id   |
+------+
|    1 |
|    2 |
|  127 |
|   50 |
+------+
4 rows in set (0.00 sec)

mysql> select * from int_test;
+--------+
| not_id |
+--------+
|      1 |
|      2 |
|    127 |
|     50 |
+--------+
4 rows in set (0.00 sec)

mysql> SELECT TABLE_NAME, DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA like '%test%';
+-----------------+-------------+
| TABLE_NAME      | DATA_LENGTH |
+-----------------+-------------+
| int_test        |          28 |
| tinyint_id_test |          28 |
| tinyint_test    |          28 |
+-----------------+-------------+
3 rows in set (0.00 sec)
我模糊地怀疑每一行中可能有一个内部列,或者给定行的最小数据大小必须至少是一个完整INT的大小,但这两种怀疑都不能真正解释这里发生的事情。可能的情况是,我选择的数据长度是测量表格真实大小的不正确工具,在这种情况下,一个可接受的答案将为我指出实际测量这些表格的正确方向

编辑:

我可以使用两个整数生成不同大小的表:

mysql> describe int_id_test;
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| id       | int(11) | YES  |     | NULL    |       |
| test_int | int(11) | YES  |     | NULL    |       |
+----------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)

mysql> select * from int_id_test;
+------+----------+
| id   | test_int |
+------+----------+
|    1 |        1 |
|    2 |        2 |
|    3 |      127 |
|   10 |       50 |
+------+----------+
4 rows in set (0.00 sec)

mysql> SELECT TABLE_NAME, DATA_LENGTH FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA like '%test%';
+-----------------+-------------+
| TABLE_NAME      | DATA_LENGTH |
+-----------------+-------------+
| int_id_test     |          36 |
| int_test        |          28 |
| tinyint_id_test |          28 |
| tinyint_test    |          28 |
+-----------------+-------------+
4 rows in set (0.01 sec)

需要注意的一点是,括号中的数字不会影响该列的大小,即INT(4)在存储方面与INT(11)的大小相同,括号中的数字所做的只是用空格填充返回值,以便填充11或4个字符

我怀疑如果你真的想计算出表的大小,你需要查看MySQL文件本身,看看它们是如何存储的。所有数据都存储在/var/lib/mysql/-ibdata中,ib_日志文件是主文件。在文本编辑器中打开此文件(注意-此文件可能很大,具体取决于数据库的大小。。也不要修改此文件!!)

所有的表和单元格都存储在这里,但是它们没有被删除,因此很难看到一列的结束和下一列的开始-这都是基于您试图建立的数据大小。如果您知道表中的数据,您应该能够计算出结构


编辑:我认为这些文件中的一些数据可能是以十六进制存储的,因此如果不能立即使用,请尝试使用十六进制编辑器。

数据长度列是操作系统分配的硬盘空间 要一张桌子

mysql数据库页面大小可配置默认为16KB,三个表的数据可能使用相同的页面,因此数据长度相同

编辑:


innodb引擎的默认页面大小是16KB,我不知道其他引擎的页面大小

我找到了解决这个问题的方法,也找到了一些解释

在hex编辑器中查看表结构(在我的linux机器上,它们位于
/var/lib/mysql/[DATABASE NAME]/[table NAME].MYD
)之后,我发现在所有情况下,记录都是使用最少7个字节的行创建的,而不管实际涉及的数据类型如何。表未使用的任何额外字节都已清零

以下是一个较小数据集的示例,以说明:

mysql> describe int_test_2;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id    | int(11) | YES  |     | NULL    |       |
+-------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> select * from int_test_2;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)
看着这个家伙在一个十六进制编辑器中,我们看到:

fd01 0000 0000 00fd 0200 0000 0000
使用Neo链接中的信息,我能够解码这一行:

  • fd
    记录头位
  • 01000000
    整数值“1”(小端)
  • 0000
    浪费空间
  • fd
    记录头位
  • 020000000
    整数值“2”(小尾端)
  • 0000
    浪费空间
但是,请注意以下事项:

mysql> alter table int_test_2 MAX_ROWS=50000000, AVG_ROW_LENGTH=4;
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0
现在,MYD文件如下所示:

fd01 0000 00fd 0200 0000

也就是说,它使用了正确的大小。

因为我的数据文件只有13吉比特,所以我认为这行不通。括号中的大小编号是在定义列时由我选择的tinyint/int设置的。我认为这与问题无关。我已经更新了我的问题,以表明我可以通过使用两个int创建不同大小的表。此外,这些是myisam表,而不是innodb。据我所知,myisam表不使用页面。@Brent Newey此页面将帮助您了解myisam记录如何存储在磁盘上