MySql 這個(gè)數(shù)據(jù)庫絕對(duì)是適合dba級(jí)的高手去玩的,一般做一點(diǎn)1萬篇新聞的小型系統(tǒng)怎么寫都可以,用xx框架可以實(shí)現(xiàn)快速開發(fā)。可是數(shù)據(jù)量到了10萬,百萬至千萬,他的性能還能那么高嗎?一點(diǎn)小小的失誤,可能造成整個(gè)系統(tǒng)的改寫,甚至更本系統(tǒng)無法正常運(yùn)行!好了,不那么多廢話了。用事實(shí)說話,看例子:
數(shù)據(jù)表 collect ( id, title ,info ,vtype) 就這4個(gè)字段,其中 title 用定長(zhǎng),info 用text, id 是逐漸,vtype是tinyint,vtype是索引。這是一個(gè)基本的新聞系統(tǒng)的簡(jiǎn)單模型。現(xiàn)在往里面填充數(shù)據(jù),填充10萬篇新聞。
select id from collect where vtype=1 order by id limit 90000,10; 很慢,用了8-9秒!
到了這里我相信很多人會(huì)和我一樣,有崩潰感覺!vtype 做了索引了啊?怎么會(huì)慢呢?vtype做了索引是不錯(cuò),你直接 select id from collect where vtype=1 limit 1000,10; 是很快的,基本上0.05秒,可是提高90倍,從9萬開始,那就是0.05*90=4.5秒的速度了。和測(cè)試結(jié)果8-9秒到了一個(gè)數(shù)量級(jí)。從這里開始有人提出了分表的思路,這個(gè)和discuz 論壇是一樣的思路。思路如下:
建一個(gè)索引表: t (id,title,vtype) 并設(shè)置成定長(zhǎng),然后做分頁,分頁出結(jié)果再到 collect 里面去找info 。 是否可行呢?實(shí)驗(yàn)下就知道了。
10萬條記錄到 t(id,title,vtype) 里,數(shù)據(jù)表大小20M左右。用
select id from t where vtype=1 order by id limit 90000,10; 很快了。基本上0.1-0.2秒可以跑完。為什么會(huì)這樣呢?我猜想是因?yàn)閏ollect 數(shù)據(jù)太多,所以分頁要跑很長(zhǎng)的路。limit 完全和數(shù)據(jù)表的大小有關(guān)的。其實(shí)這樣做還是全表掃描,只是因?yàn)閿?shù)據(jù)量小,只有10萬才快。OK, 來個(gè)瘋狂的實(shí)驗(yàn),加到100萬條,測(cè)試性能。
答案就是:復(fù)合索引! 有一次設(shè)計(jì)mysql索引的時(shí)候,無意中發(fā)現(xiàn)索引名字可以任取,可以選擇幾個(gè)字段進(jìn)來,這有什么用呢?開始的select id from collect order by id limit 90000,10; 這么快就是因?yàn)樽吡怂饕墒侨绻恿藈here 就不走索引了。抱著試試看的想法加了 search(vtype,id) 這樣的索引。然后測(cè)試
select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!
再測(cè)試: select id ,title from collect where vtype=1 limit 90000,10; 非常遺憾,8-9秒,沒走search索引!
再測(cè)試:search(id,vtype),還是select id 這個(gè)語句,也非常遺憾,0.5秒。
$db->execute($sql); $strpage=$db->strpage(); //將分頁字符串保存在臨時(shí)變量,方便輸出 while($rs=$db->fetch_array()){ $strid.=$rs['id'].','; } $strid=substr($strid,0,strlen($strid)-1); //構(gòu)造出id字符串 $db->pagesize=0; //很關(guān)鍵,在不注銷類的情況下,將分頁清空,這樣只需要用一次數(shù)據(jù)庫連接,不需要再開; $db->execute("select id,title,url,sTime,gTime,vtype,tag from collect where id in ($strid)");
PS: 經(jīng)過實(shí)際測(cè)試,到了100萬的數(shù)據(jù),160萬數(shù)據(jù),15G表,190M索引,就算走索引,limit都得0.49秒。所以分頁最好別讓別人看到10萬條以后的數(shù)據(jù),要不然會(huì)很慢!就算用索引。經(jīng)過這樣的優(yōu)化,mysql到了百萬級(jí)分頁是個(gè)極限!但有這樣的成績(jī)已經(jīng)很不錯(cuò),如果你是用sqlserver肯定卡死!而160萬的數(shù)據(jù)用 id in (str) 很快,基本還是0秒。如果這樣,千萬級(jí)的數(shù)據(jù),mysql應(yīng)該也很容易應(yīng)付。