2016-11-05 76 views
0

我想問問MySQL innodb你建議如何獲得一個更小的數據庫?innodb節省存儲空間

我沒有innodb_file_per_table,但我不需要回收空間(這將很高興看到我能夠節省多少空間)。

大部分字符串保存爲utf8mb4。對於一些列我可以使用latin1(我知道那裏只能有拉丁字符)。如果我將它們轉換爲latin1,你認爲我可以節省很多空間嗎?看來這種改變也會讓你的搜索性能提高。

我已經定義了大量文本爲MEDIUMTEXT的列。如果我將該列定義爲TEXT,您認爲我應該節省一些空間嗎? - 從我看到這種類型的行爲像VARCHAR(它只佔用字符串的長度)

您還有什麼其他建議?

該數據庫擁有超過300個百萬行,並存儲在100G左右

感謝

+0

你在儲存什麼?這是一個數據庫的一部分,知道你正在存儲什麼類型的數據,以及是否有值得改變的數據,以最大限度地減少數據量是很有趣的。 – junkfoodjunkie

+0

_英語字母在拉丁文中採用與utf8中相同的1個字節。 –

+0

請提供'SHOW CREATE TABLE';可能會有其他提示(標準化,整數大小,標誌等)。 –

回答

1

更改字符集也無濟於事。當您使用utf8或utf8mb4時,每個字符都存儲在可變數量的字節中。可以存儲在單個字節中的字符以這種方式存儲。

從MEDIUMTEXT更改爲TEXT不會有太大幫助。這些列中的每個字符串都以可變長度存儲,只能保存到您存儲的字符串所需的長度。 TEXT可以存儲高達64KB的字符串,MEDIUMTEXT可以存儲高達16MB的字符串。我想每個這樣的字符串可能需要一個單一的長度指示符,這將是每個TEXT兩個字節和每個MEDIUMTEXT三個字節。所以你可以在整個數據庫中最多節省300MB每列(可能甚至不會那麼多)。這不會產生足夠的差異。

你可以找出你的表空間有多少可用空間。運行SHOW TABLE STATUS LIKE 'sometable'其中「sometable」是表空間中任何表的名稱。

返回的字段之一是data_free。這是表空間中的可用空間字節數。當在同一個全局表空間中有多個表時,每個表都報告相同的值。這並不意味着你的自由空間是所有這些數字的總和,實際上它是每個表格狀態重複的一個空閒空間。

爲了節省空間,一些人宣稱InnoDB的故事與ROW_FORMAT=COMPRESSED,但這需要您使用文件每表。由於您已經在全局表空間中擁有表,因此即使將表重構爲每個表的文件,它也不會縮小全局表空間。當你將表移動到它們自己的文件中時,它只會留下一個大部分爲空的巨大的全局表空間。所以這隻會讓你的存儲問題變得更糟。

我可以建議的唯一事情就是你要做以下步驟。當你這樣做時,沒有人可以使用你的數據庫。

  1. 轉儲InnoDB表中的所有數據,並在必要時將轉儲的輸出保存到另一個卷。哪裏有空間。您可以壓縮轉儲的輸出:

    mysqldump ... | gzip -c > dump.sql.gz 
    
  2. 停止您的mysqld進程。

  3. 刪除您的整個全局表空間,即rm /var/lib/mysql/ibdata1和您可能仍有的任何* .ibd文件。 當然,您應該首先進行備份。
  4. 在您的/etc/my.cnf中啓用innodb_file_per_table。還根據MySQL的版本啓用innodb_file_format=Barracuda
  5. 啓動你的mysqld進程。它會自動將全局表空間重新創建爲新的小文件。
  6. 恢復您傾銷的表格。它們將被放入獨立的InnoDB文件中,而不是全局表空間。
  7. 如有必要,ALTER每個表使用ROW_FORMAT=COMPRESSED

這顯然需要很長時間來轉儲和重新加載300M行。這將需要許多小時,並且在此期間您的數據庫將無法使用。

如果在執行此過程時無法讓數據庫不可用,則必須在副本上執行此操作,並且在完成過程並且副本與主服務器同步後,您可以快速將主副本替換爲副本。這在切換時仍會導致服務短暫中斷,但速度很快。

下次開始時爲您的數據庫服務器提供更大的存儲卷。計劃您需要的存儲量並對其進行計劃。


重新發表您的評論,即您已從MEDIUMTEXT更改爲TEXT並保存了空間。

INFORMATION_SCHEMA中的大小(與SHOW TABLE STATUS報告的大小相同)只是估計值,它們可能已過時或以其他方式關閉。偶爾運行ANALYZE TABLE可以更新統計信息。

一個表也可以被分割,並且偶爾重建它可以回收一些空間。使用OPTIMIZE TABLE。

另一種可能性是您的MEDIUMTEXT列實際上存儲的文本字符串長度超過TEXT列的長度,並且您的ALTER TABLE會截斷它們。

這裏有一個演示:

mysql> create table m (m mediumtext); 

mysql> insert into m set m = repeat('X', 1024*1024*2); 
Query OK, 1 row affected (0.05 sec) 

mysql> select length(m) from m; 
+-----------+ 
| length(m) | 
+-----------+ 
| 2097152 | 
+-----------+ 

mysql> alter table m modify column m text; 
Query OK, 1 row affected (0.01 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

mysql> select length(m) from m; 
+-----------+ 
| length(m) | 
+-----------+ 
|   0 | 
+-----------+ 

我填補了MEDIUMTEXT數據的2MB,然後使用ALTER給列更改爲TEXT。它不會簡單地截斷爲可以放入TEXT列的64KB,它會將文本截斷爲零個字符。

所以,我希望你不只是消滅所有的文本數據。

+0

非常感謝您提供完整的答案。 我將MEDIUMTEXT colums改爲TEXT,結果比預期好很多。我能夠釋放30G。我不確定這是否屬實(也許information_schema無效)。一些具有MEDIUMTEXT列的表現在小2-3倍 - 所以現在這些表甚至比僅具有varchar和int的表小 – user1611597