由MySQL中char和varchar效率想到的

2021-05-22 09:07:20 字數 4706 閱讀 7278

一般認為空間換時間,現在磁碟又大又不值錢!

當使用全表都是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個額外位元組...