如今咱們繼續進行一個測試相同的表結構插入1億條數據此次用到的是Innodb表引擎,表名有些變化,這裏爲甚要新建一個表的很重要元素是原來的那張表是每一個uid=1來作的索引,此次uid是1...10不等的數每種1千萬條記錄
CREATE TABLE `ipdata` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(8) NOT NULL DEFAULT '0',
`ipaddress` varchar(50) NOT NULL,
`source` varchar(255) DEFAULT NULL,
`track` varchar(255) DEFAULT NULL,
`entrance` varchar(255) DEFAULT NULL,
`createdtime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`createddate` date NOT NULL DEFAULT '0000-00-00',
PRIMARY KEY (`id`),
KEY `uid` (`uid`)
} ENGINE=InnoDB AUTO_INCREMENT=100004857 DEFAULT CHARSET=utf8
我開啓了Innodb的線程數爲128,由於innodb是行級別鎖定,併發處理能力很強我開啓100線程每一個線程大小爲100萬記錄插入時間以下
JDBC插入100w條數據此線程用時:9300984ms
JDBC插入100w條數據此線程用時:9381203ms
JDBC插入100w條數據此線程用時:9412343ms
JDBC插入100w條數據此線程用時:9442046ms
JDBC插入100w條數據此線程用時:9449828ms
JDBC插入100w條數據此線程用時:9484703ms
JDBC插入100w條數據此線程用時:9528093ms
JDBC插入100w條數據此線程用時:9533359ms
JDBC插入100w條數據此線程用時:9534296ms
JDBC插入100w條數據此線程用時:9539718ms
JDBC插入100w條數據此線程用時:9541750ms
JDBC插入100w條數據此線程用時:9636406ms
JDBC插入100w條數據此線程用時:9695093ms
JDBC插入100w條數據此線程用時:9806890ms
JDBC插入100w條數據此線程用時:9895500ms
JDBC插入100w條數據此線程用時:9989750ms
JDBC插入100w條數據此線程用時:10012312ms
JDBC插入100w條數據此線程用時:10037250ms
JDBC插入100w條數據此線程用時:10092796ms
JDBC插入100w條數據此線程用時:11993187ms
JDBC插入100w條數據此線程用時:12033203ms
JDBC插入100w條數據此線程用時:12068453ms
JDBC插入100w條數據此線程用時:12133625ms
JDBC插入100w條數據此線程用時:12212953ms
JDBC插入100w條數據此線程用時:12253421ms
JDBC插入100w條數據此線程用時:12284968ms
JDBC插入100w條數據此線程用時:12296421ms
JDBC插入100w條數據此線程用時:12366828ms
JDBC插入100w條數據此線程用時:12388093ms
JDBC插入100w條數據此線程用時:12389656ms
JDBC插入100w條數據此線程用時:12396625ms
JDBC插入100w條數據此線程用時:12417921ms
JDBC插入100w條數據此線程用時:12431000ms
JDBC插入100w條數據此線程用時:12432875ms
JDBC插入100w條數據此線程用時:12434703ms
JDBC插入100w條數據此線程用時:12455218ms
JDBC插入100w條數據此線程用時:12457109ms
JDBC插入100w條數據此線程用時:12484218ms
JDBC插入100w條數據此線程用時:12518375ms
JDBC插入100w條數據此線程用時:12519015ms
JDBC插入100w條數據此線程用時:12521109ms
JDBC插入100w條數據此線程用時:12521515ms
JDBC插入100w條數據此線程用時:12537343ms
JDBC插入100w條數據此線程用時:12539421ms
JDBC插入100w條數據此線程用時:12544250ms
JDBC插入100w條數據此線程用時:12559234ms
JDBC插入100w條數據此線程用時:12567484ms
JDBC插入100w條數據此線程用時:12574109ms
JDBC插入100w條數據此線程用時:12579156ms
JDBC插入100w條數據此線程用時:12638046ms
JDBC插入100w條數據此線程用時:12693047ms
JDBC插入100w條數據此線程用時:12722906ms
JDBC插入100w條數據此線程用時:12728781ms
JDBC插入100w條數據此線程用時:12732546ms
JDBC插入100w條數據此線程用時:12748265ms
JDBC插入100w條數據此線程用時:12757421ms
JDBC插入100w條數據此線程用時:12761375ms
JDBC插入100w條數據此線程用時:12765312ms
JDBC插入100w條數據此線程用時:12788359ms
JDBC插入100w條數據此線程用時:12802765ms
JDBC插入100w條數據此線程用時:12810484ms
JDBC插入100w條數據此線程用時:12811062ms
JDBC插入100w條數據此線程用時:12811796ms
JDBC插入100w條數據此線程用時:12812843ms
JDBC插入100w條數據此線程用時:12829671ms
JDBC插入100w條數據此線程用時:12830296ms
JDBC插入100w條數據此線程用時:12840000ms
JDBC插入100w條數據此線程用時:12840890ms
JDBC插入100w條數據此線程用時:12850312ms
JDBC插入100w條數據此線程用時:12856671ms
JDBC插入100w條數據此線程用時:12858609ms
JDBC插入100w條數據此線程用時:12860125ms
JDBC插入100w條數據此線程用時:12861750ms
JDBC插入100w條數據此線程用時:12864125ms
JDBC插入100w條數據此線程用時:12875609ms
JDBC插入100w條數據此線程用時:12875781ms
JDBC插入100w條數據此線程用時:12900859ms
JDBC插入100w條數據此線程用時:12906812ms
JDBC插入100w條數據此線程用時:12909656ms
JDBC插入100w條數據此線程用時:12913375ms
JDBC插入100w條數據此線程用時:12915609ms
JDBC插入100w條數據此線程用時:12917562ms
JDBC插入100w條數據此線程用時:12918000ms
JDBC插入100w條數據此線程用時:12919468ms
JDBC插入100w條數據此線程用時:12922093ms
JDBC插入100w條數據此線程用時:12922843ms
JDBC插入100w條數據此線程用時:12924375ms
JDBC插入100w條數據此線程用時:12925734ms
JDBC插入100w條數據此線程用時:12925781ms
JDBC插入100w條數據此線程用時:12931140ms
JDBC插入100w條數據此線程用時:12934562ms
JDBC插入100w條數據此線程用時:12934828ms
JDBC插入100w條數據此線程用時:12935281ms
JDBC插入100w條數據此線程用時:12936953ms
JDBC插入100w條數據此線程用時:12937218ms
JDBC插入100w條數據此線程用時:12937406ms
JDBC插入100w條數據此線程用時:12937765ms
JDBC插入100w條數據此線程用時:12939125ms
JDBC插入100w條數據此線程用時:12940281ms
JDBC插入100w條數據此線程用時:12941828ms
大概一共用了2個多小時內容爲1億條數據mysql的innodb中文件大小爲 11.7 GB (12,660,506,624 字節);
首先來看看in查詢
SELECT * FROM ipdata WHERE id IN(112358,201023,100020,100001,10000,100000,1000000,10000000,100000000); 141ms
SELECT * FROM ipdata WHERE id IN(12345,123456,1234567,12345678,987654,789654,1236985,852963,9745621,78965412); 141ms
看來in的查詢還算理想,
而後咱們進行分頁必要查詢不排序
SELECT id FROM ipdata WHERE uid=1 LIMIT 1,10; 31ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 100,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 1000,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10000,10; 47ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 100000,10; 235ms;
SELECT id FROM ipdata WHERE uid=1 LIMIT 1000000,10; 1.438s;
SELECT id FROM ipdata WHERE uid=1 LIMIT 5000000,10; 5.422s;
SELECT id FROM ipdata WHERE uid=1 LIMIT 10000000,10; 9.562s; 無返回結果
SELECT id FROM ipdata WHERE uid=1 LIMIT 9999990,10; 10.953s;
符合上一篇的結論mysql越向後越慢,可是總體來講是能夠接受的,畢竟分頁到最後一頁雖然用到了10秒鐘,可是後臺人員不可能到最後去看,第二呢,10秒後臺人員也算能夠接受級別;mysql
分頁排序查詢
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000,10; 0ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10000,10; 47ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100000,10; 266ms;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10; 1.594s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 5000000,10; 5.625s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id DESC LIMIT 5000000,10; 11.235s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10000000,10; 11.562s 無返回結果
SELECT id FROM ipdata WHERE uid=1 ORDER BY ID ASC LIMIT 9999990,10; 11.719s;
SELECT id FROM ipdata WHERE uid=1 ORDER BY ID DESC LIMIT 9999990,10; 18.719s;
結論是若是單查找id,order by的時間比較可觀,可是可見正序和倒序時間不一樣.web
返回所有結果查詢"*"
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1,10; 109ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10,10; 0ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100,10; 16ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000,10; 63ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 10000,10; 356ms;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 100000,10; 2.969s;
SELECT * FROM ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10; 30.766s;
select id,uid,ipaddress,source,track,entrance,createdtime,createddate from ipdata WHERE uid=1 ORDER BY id ASC LIMIT 1000000,10; 29.953s;
...下面的就不測試了,已經難以接受了
結論SELECT id 要比SELECT *快了很多至少在大的結果面前;sql
結果count測試
SELECT COUNT(*) FROM ipdata WHERE uid=1; 12.281s;
SELECT COUNT(*) FROM ipdata WHERE uid=2; 12.250s;
....
SELECT COUNT(*) FROM ipdata WHERE uid=10; 11.453s;
count級別大概是10多秒左右返回都是1000萬;數據庫
Count(id)測試
SELECT COUNT(id) FROM ipdata WHERE uid=1; 10.281s;
SELECT COUNT(id) FROM ipdata WHERE uid=2; 10.531s;
....
SELECT COUNT(id) FROM ipdata WHERE uid=10; 12.531s;
Count(id)這裏我不知道是機器緣由可能測試不是十分準確,總之相差不大,不知道是否mysql默認經過惟一主鍵來count,若是*和id差很少都方便我仍是推薦id,呵呵緩存
這樣咱們能夠經過SELECT id 來獲得id列表,而後經過in來獲得相應的記錄,可見是可行的;還有在此次測試中咱們經過uid這個屬性來過濾掉了90%的結果集,若是根據95%過濾理 想化可能還有點欠缺,可是根據80%過濾原則就不一樣了,至少這個索引仍是理想的,過濾掉的內容看來mysql就能夠算到千萬級別的用時了。其實這裏面的時 間不表明真實時間,畢竟機器也是咱們辦公室一臺pc電腦,數據也比較小,這裏我只是有時間來測試一下千萬條乃至上億條數據的處理能力,到服務器上應該要比 這個快不少,畢竟磁盤io差距大,並且cpu也有差距,
總結
1.mysql千萬級別數據確定是沒問題的,畢竟如今的流向web2.0網站大部分是mysql的
2.合理分表也是必須的,主要涉及橫向分表與縱向分表,如把大小字段分開,或者每100萬條記錄在一張表中等等,像上面的這個表能夠考慮經過uid的範圍分表,或者經過只創建索引表,去掉相對大的字段來處理.
3.count()時間比較長,可是自己是能夠緩存在數據庫中或者緩存在程序中的,由於咱們當時使用在後臺因此第一頁比較慢可是後面比較理想
4.SELECT id 相對SELECT * 差距仍是比較大的,能夠經過上面的方法來使用SELECT id + SELECT * ... IN 查詢來提升性能
5.必要的索引是必須的,仍是要儘可能返回5%-20%的結果級別其中小於5%最理想;
6.mysql分頁的前面幾頁速度很快,越向後性能越差,能夠考慮只帶上一頁,下一頁不帶頁面跳轉的方法,呵呵這個比較垃圾可是也算是個方案,只要在先後多查一條就能解決了.好比100,10 你就差99,12呵呵,這樣看看先後是否有結果.
7.前臺仍是要經過其餘手段來處理,好比lucene/Solr+mysql結合返回翻頁結果集,或者上面的分表
8. 1億的數據還在咱們這裏你們能夠充分考慮搜索條件 我幫你們測試哈哈。服務器
接下來我將要測試一些關於1億+的用戶數據表的解決方案,及大數據的搜索方案經過lucene/solr+mysql併發