2011-04-27 66 views
4

當我遇到一些有趣的事情時,我試圖測量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的大小,但這些懷疑都不能解釋這裏發生的事情。什麼可能是這樣的情況是我選擇DATA_LENGTH是測量表的真實大小的不正確的工具,在這種情況下,一個可接受的答案會指向我實際測量這些表的正確方向。

編輯:

我可以用兩個整數生成不同大小的表:

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) 

回答

1

我已經發現了這個問題的解決辦法,以及一個解釋的東西。

在十六進制編輯器(在我的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 

來自新的鏈接使用的信息,我是能夠解碼此行:

  • fd記錄標頭位。
  • 01000000整數值「1」(小端)
  • 0000浪費空間!
  • fd記錄標題位。
  • 02000000整數值「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 

也就是說,它採用正確的大小。

-1

有一點需要注意的是,在括號內的數字不會影響該列的大小,即INT(4)在存儲方面與INT(11)的大小相同,括號中的所有數字都是用空格填充返回值,以便填充11或4個字符。

我懷疑如果你真的想弄清表的大小,你需要查看MySQL文件本身,看看它們是如何存儲的。所有的數據存儲在/ var/lib/mysql/- ibdata & ib_logfile是主要文件。在文本編輯器打開此(注意 - 此文件可根據您的數據庫的大小是巨大的..也切勿修改此文件!!)

所有的表格和單元格都存儲在這裏,但他們沒有被隔離,所以很難看到一列的結束和下一個開始 - 這一切都基於你試圖建立的數據大小。如果你知道表格中的數據,你應該能夠計算出結構。

編輯:我認爲這些文件中的一些數據可能以十六進制存儲,所以如果它沒有立即有意義,請嘗試使用十六進制編輯器。

+0

由於我的數據文件只是13 Gig的害羞,我不認爲這會工作。當我定義列時,括號中的大小號由我選擇的tinyint/int設置。我不相信這與問題有關。 – 2011-04-27 15:37:01

1

data_length列是操作系統爲表分配 多少硬盤空間。

mysql數據庫的頁面大小可配置默認爲16KB,這三個表的數據可能會使用相同的頁面,所以data_length是一樣的!

編輯:

InnoDB引擎的默認頁面大小爲16KB,我不知道這個尺寸的其他引擎

+0

我已更新我的問題,以顯示我可以簡單地通過使用兩個INT創建不同大小的表。另外,這些是myisam表,而不是innodb。從我的理解myisam表不使用網頁。 – 2011-04-27 16:31:47

+0

@Brent Newey http://bit.ly/kO4fxT這個頁面將幫助你理解myisam記錄如何存儲在磁盤上 – Neo 2011-04-28 01:32:07

相關問題