一般認為空間換時間,現在磁碟又大又不值錢!
當使用全表都是char這的字段的時候,那麼表屬性row_format是fixed也就是靜態表,與之對應的自然就是動態表dynamic,靜態錶比動態表效率要高,主要是因為,基於兩點:
1)沒有碎片,每行的長度是固定,所以在頻繁更新的場景下,尤其是某個欄位由小變大.
2)方便資料檔案指標的操作,在myisam中有乙個資料檔案指標的概念,是用來指向資料檔案,比如在索引中指向資料檔案.靜態表的偏移量的固定不變的,而在動態表中每行的資料長度大小不一,就可能導致資料更多的開銷
基於以上兩點,所以靜態表在查詢,修改擁有較大優勢,但是這個優勢也是有適用場景的.
首先猜想char由於每次訪問都會自動的削掉末尾的空格,而且資料檔案也大,所以會使用更多的cpu和記憶體資源,尤其在取的時候,要是長短差距較大的時候,還是會很浪費操作的.
其次驗證想法,首先測試插入效能,建了2張表並呼叫sp分別插入200w的資料
create table `isam_char` (
`content` char(255) not null
) engine=myisam default charset=utf8;
create table `isam_vc` (
`content` varchar(255) not null
) engine=myisam default charset=utf8;
call insert_isam(2000000,'isam_char');
call insert_isam(2000000,'isam_vc');
多次平均isam_char插入200w的資料為138.21s,而isam_vc少了約20s為119.80s,這應該是每次插入的時候,mysql要把char欄位填充到255的操作.觀察資料檔案大小,isam_vc為235.8m而isam_char為1.4g!
再測試查詢,為了保證兩者一致,首先把isam_char中資料刪除,再把isam_vc中資料匯入isam_char中,無索引,禁閉query_cache
truncate table isam_char;##觀察了下資料檔案,被窮空成0
insert into isam_char select * from isam_vc;##觀察了下資料檔案,依然是1.4g
select * from isam_char limit 1555555,5;
select * from isam_vc limit 1555555,5;
依舊多次查詢去平均值,isam_char表平均值為10.50s,而isam_vc則為1.51s!
再看下建立索引,以及索引的使用情況
mysql> create index index_char on isam_char(content);
query ok, 2000001 rows affected (2 min 56.33 sec)
records: 2000001 duplicates: 0 warnings: 0
mysql> create index index_vc on isam_vc(content);
query ok, 2000001 rows affected (1 min 31.98 sec)
records: 2000001 duplicates: 0 warnings: 0
mysql> select count(*) from isam_char where content=('iamauperman!iwillbeahero!!');
+----------+
| count(*) |
+----------+
| 199669 |
+----------+
1 row in set (0.56 sec)
mysql> select count(*) from isam_vc where content=('iamauperman!iwillbeahero!!');
+----------+
| count(*) |
+----------+
| 199669 |
+----------+
1 row in set (0.31 sec)
還是不理想,所以在長度很不固定情況下使用char或靜態表是很不理想的事,當然這裡做的是全索引掃瞄,動態表的索引要小於動態表,估計最大的優勢是使用索引去找資料和update,為了驗證,再次測試update.
mysql> update isam_char set content='iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!';
query ok, 2000001 rows affected (54 min 54.25 sec)
rows matched: 2000001 changed: 2000001 warnings: 0
mysql> update isam_vc set content='iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!iwillbeahero!!iamauperman!';
query ok, 2000001 rows affected (1 hour 59 min 25.73 sec)
rows matched: 2000001 changed: 2000001 warnings: 0
果然啊,更新200w的資料差了1倍多!同時動態表的資料增大為480.7m.順便讀了幾次資料,依然有差距
mysql> select count(*) from isam_vc ignore index(index_vc) where content='iamauperman!iwillbeahero!
!';
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (10.55 sec)
mysql> select count(*) from isam_char ignore index(index_char) where content='iamauperman!iwillbeah
ero!!';
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (14.98 sec)
不使用索引,做全表掃瞄,動態表快於靜態表,這可能是資料檔案大小的差異吧.
由於資料來源和時間的問題,今天就不做掃瞄完索引再去讀資料的實驗了.
基本得出結論:mysql裡,準確的說是myisam引擎中,靜態表又或者char的長處在於更新操作,讀取(不使用索引讀取)和插入相比varchar又或動態表,並無優勢.
本測試環境為winxp+mysql-5.1.44-community,配置為mysql預設配置.無修改.
注:做這個測試說明我好奇心很強,還有就是我真的很無聊,假如你看了,覺得錯了,有明顯漏洞的地方,歡迎指正!你也別罵我,我知道我是菜鳥,mysql程式不是有個選項叫做—i-am-a-dummy嗎,我就是乙個dummy,呵呵,浪費你的時候,我知道我錯了!
附:插資料的sp
create definer=`root`@`localhost` procedure `insert_isam`(p int,t char(10))
begin
set @i = 0;
set @str = "iamauperman!iwillbeahero!!";
repeat
#select name into @str from mysql.help_topic order by rand() limit 1;
set @str=substr(@str,1,25);
set @ins_str = repeat(@str,floor(rand()*10));
set @cmd=concat('insert into ',t,' (content) values("',@ins_str,'")');
prepare stmt from @cmd;
execute stmt;
set @i = @i+1;
until @i > p end repeat;
end
由MySQL中char和varchar效率想到的
一般認為空間換時間,現在磁碟又大又不值錢 當使用全表都是char這的字段的時候,那麼表屬性row format是fixed也就是靜態表,與之對應的自然就是動態表dynamic,靜態錶比動態表效率要高,主要是因為,基於兩點 1 沒有碎片,每行的長度是固定,所以在頻繁更新的場景下,尤其是某個欄位由小變大...
mysql中char和varchar區別
結論 char 定長,效率高 varchar 不定長,效率低。char是一種固定長度的型別,varchar則是一種可變長度的型別,它們的區別是 char m 型別的資料列裡,每個值都占用m個位元組,如果某個長度小於m,mysql就會在它的右邊用空格字元補足 在檢索操作中那些填補出來的空格字元將被去掉...
MySQL中varchar 和char型別介紹
varchar 和char型別是兩種最重要的字串型別,在儲存引擎是innodb或myisam下,討論varchar和char。一 varchar型別 varchar 用於可變長字串,是最常見的字串資料型別。它比定長型別更節省空間,按照儲存的實際字串長度分配空間。varchar需使用1或2個額外位元組...