一、Mysql使用delete刪除數據後,不釋放空間
當你刪除數據 時,mysql並不會回收,被已刪除數據的佔據的存儲空間,以及索引位。而是空在那裏,而是等待新的數據來彌補這個空缺,這樣就有一個缺少,如果一時半 會,沒有數據來填補這個空缺,那這樣就太浪費資源了。所以對於寫比較頻煩的表,要定期進行optimize,一個月一次,看實際情況而定了。
A,原始數據
1,count一下
mysql> select count(*) as total from ad_visit_history;
+---------+
| total |
+---------+
| 1187096 | //總共有118萬多條數據
+---------+
1 row in set (0.04 sec)
2,存放在硬盤中的表文件大小
[root@BlackGhost test1]# ls |grep visit |xargs -i du {}
382020 ad_visit_history.MYD //數據文件佔了380M
127116 ad_visit_history.MYI //索引文件佔了127M
12 ad_visit_history.frm //結構文件佔了12K
3,查看一下索引信息
mysql> show index from ad_visit_history from test1; //查看一下該表的索引信息
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| ad_visit_history | 0 | PRIMARY | 1 | id | A | 1187096 | NULL | NULL | | BTREE | |
| ad_visit_history | 1 | ad_code | 1 | ad_code | A | 46 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | unique_id | 1 | unique_id | A | 1187096 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ad_code_ind | 1 | ad_code | A | 46 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | from_page_url_ind | 1 | from_page_url | A | 30438 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ip_ind | 1 | ip | A | 593548 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | port_ind | 1 | port | A | 65949 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | session_id_ind | 1 | session_id | A | 1187096 | NULL | NULL | YES | BTREE | |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
8 rows in set (0.28 sec)
索引信息中的列的信息說明。
Table :表的名稱。 Non_unique :如果索引不能包括重複詞,則爲0。如果可以,則爲1。 Key_name :索引的名稱。 Seq_in_index :索引中的列序列號,從1開始。 Column_name :列名稱。 Collation :列以什麼方式存儲在索引中。在MySQLSHOW INDEX語法中,有值’A’(升序)或NULL(無分類)。 Cardinality :索引中唯一值的數目的估計值。通過運行ANALYZE TABLE或myisamchk -a可以更新。基數根據被存儲爲整數的統計數據來計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL使用該索引的機會就越大。 Sub_part :如果列只是被部分地編入索引,則爲被編入索引的字符的數目。如果整列被編入索引,則爲NULL。 Packed :指示關鍵字如何被壓縮。如果沒有被壓縮,則爲NULL。 Null :如果列含有NULL,則含有YES。如果沒有,則爲空。 Index_type :存儲索引數據結構方法(BTREE, FULLTEXT, HASH, RTREE)
B,刪除一半數據
mysql> delete from ad_visit_history where id>598000; //刪除一半數據
Query OK, 589096 rows affected (4 min 28.06 sec)
[root@BlackGhost test1]# ls |grep visit |xargs -i du {} //相對應的MYD,MYI文件大小沒有變化
382020 ad_visit_history.MYD
127116 ad_visit_history.MYI
12 ad_visit_history.frm
按常規思想來說,如果在數據庫中刪除了一半數據後,相對應的.MYD,.MYI文件也應當變爲之前的一半。但是刪除一半數據後,.MYD.MYI盡然連1KB都沒有減少 ,這是多麼的可怕啊。
我們在來看一看,索引信息
Mysql> show index from ad_visit_history;
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| ad_visit_history | 0 | PRIMARY | 1 | id | A | 598000 | NULL | NULL | | BTREE | |
| ad_visit_history | 1 | ad_code | 1 | ad_code | A | 23 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | unique_id | 1 | unique_id | A | 598000 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ad_code_ind | 1 | ad_code | A | 23 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | from_page_url_ind | 1 | from_page_url | A | 15333 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ip_ind | 1 | ip | A | 299000 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | port_ind | 1 | port | A | 33222 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | session_id_ind | 1 | session_id | A | 598000 | NULL | NULL | YES | BTREE | |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
8 rows in set (0.00 sec)
對比一下,這次索引查詢和上次索引查詢,裏面的數據信息基本上是上次一次的一本,這點還是合乎常理。
C,用optimize table來優化一下
注意:使用optimize命令會鎖表,慎用
mysql> optimize table ad_visit_history; //刪除數據後的優化
+------------------------+----------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+------------------------+----------+----------+----------+
| test1.ad_visit_history | optimize | status | OK |
+------------------------+----------+----------+----------+
1 row in set (1 min 21.05 sec)
1,查看一下.MYD,.MYI文件的大小
[root@BlackGhost test1]# ls |grep visit |xargs -i du {}
182080 ad_visit_history.MYD //數據文件差不多爲優化前的一半
66024 ad_visit_history.MYI //索引文件也一樣,差不多是優化前的一半
12 ad_visit_history.frm
2,查看一下索引信息
mysql> show index from ad_visit_history;
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
| ad_visit_history | 0 | PRIMARY | 1 | id | A | 598000 | NULL | NULL | | BTREE | |
| ad_visit_history | 1 | ad_code | 1 | ad_code | A | 42 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | unique_id | 1 | unique_id | A | 598000 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ad_code_ind | 1 | ad_code | A | 42 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | from_page_url_ind | 1 | from_page_url | A | 24916 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | ip_ind | 1 | ip | A | 598000 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | port_ind | 1 | port | A | 59800 | NULL | NULL | YES | BTREE | |
| ad_visit_history | 1 | session_id_ind | 1 | session_id | A | 598000 | NULL | NULL | YES | BTREE | |
+------------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
8 rows in set (0.00 sec)
從以上數據我們可以得出,ad_code,ad_code_ind,from_page_url_ind等索引機會差不多都提高了85%,這樣效率提高了好多。
二、Mysql相關命令(是否釋放磁盤空間)
drop table table_name 立刻釋放磁盤空間 ,不管是 Innodb和MyISAM ;
truncate table table_name立刻釋放磁盤空間 ,不管是 Innodb和MyISAM;
delete from table_name 刪除表的全部數據,對於MyISAM 會立刻釋放磁盤空間 ,而InnoDB 不會釋放磁盤空間;
delete from table_name where xx 帶條件的刪除, 不管是innodb還是MyISAM都不會釋放磁盤空間;
delete操作後使用optimize table table_name 釋放磁盤空間,優化表期間會鎖定表,所以要在空閒時段執行optimize table ,測試十幾個G數據的表執行optimize table 大概20多分鐘。
注:delete刪除數據的時候,mysql並沒有把數據文件刪除,而是將數據文件的標識位刪除,沒有整理文件,因此不會徹底釋放空間。被刪除的數據將會被保存在一個鏈接清單中,當有新數據寫入的時候,mysql會利用這些已刪除的空間再寫入。即,刪除操作會帶來一些數據碎片,正是這些碎片在佔用硬盤空間。
OPTIMIZE TABLE命令優化表,該命令會重新利用未使用的空間,並整理數據文件的碎片;該命令將會整理表數據和相關的索引數據的物理存儲空間,用來減少佔用的磁盤空間,並提高訪問表時候的IO性能;但是具體對錶產生的影響是依賴於表使用的存儲引擎的。該命令對視圖無效。
使用optimize table table_name出現Table does not support optimize, doing recreate + analyze instead 的解決辦法:
innodb的數據庫不支持optimize,可以用 ALTER TABLE table.name ENGINE='InnoDB';對舊錶以複製的方式新建一個新表,然後刪除舊錶。操作前最好備份表。
重新啓動mysql ,在啓動的時候指定–skip-new或者–safe-mode選項來支持optimize功能 再執行optimize table table_name
>/usr/local/mysql/bin/mysqladmin -uroot -p shutdown --停止mysql
>/usr/local/mysql/bin/mysqld --skip-new & --啓動mysql
>mysql -uroot -p --在服務器上連接mysql
mysql>use db_name;
刪除數據並執行了optimize table釋放了磁盤空間;optimize命令優化表 不要頻繁操作,另外還發現執行optimize命令 Innodb 引擎的數據庫下ibtmp1 文件由原來的幾個G優化成12M了。
但如果數據每天都大量插入,刪除數據後不執行optimize table insert 數據的時候會佔用已經刪除那部分數據的空間,數據文件所佔用的磁盤空間短時間並不會增長,所以要減少數據文件佔用磁盤空間,可以對錶進行壓縮。
三、是否對InnoDB數據表進行壓縮
適用於I/O爲系統主要瓶頸的應用系統,表壓縮可以增加I/O吞吐,但是同時解壓縮會耗費cpu資源。所以本質上是以cpu換I/O。
優點:
1、文件大小減小(可達50%以上)
壓縮後
2、 查詢速度變快(count * 約減少20%以上時間)
如何設置mysql innodb 表的壓縮:
第一,mysql的版本需要大於5.5
第二,設置innodb_file_format=barracuda
第三,create table或者alter talble 增加 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;(默認的key_block_size=16)
根據經驗,一般壓縮比例可以達到30%-40%
順序不能改變, 先設置字符集給事爲 innodb_file_format=barracuda,然後再建表或者修改表的compaesed 。