6,ORM组件XCode(撬动千万级数据)
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
??? 有了前面的《動手》,基本上可以進行開發(fā)了。本篇我們來試試XCode的基本功功力如何,測試在單表一千萬業(yè)務數(shù)據(jù)的環(huán)境下查詢的速度,添刪改等沒什么可測試的。其實應該說是XCode開發(fā)模式的功力,XCode組件僅僅是處理分頁而已,而XCode開發(fā)模式為高性能開發(fā)提供了更多的建議。
??? 測試環(huán)境:雙核CPU,4G內(nèi)存,win7+SQL2008+vs2010
??? 數(shù)據(jù)表字段包括:自增ID、車牌、時間。使用SQL準備一千萬測試數(shù)據(jù),花了將近一個小時。
??? 測試用例:ID的升序降序,時間的升序降序,每一種情況測試取首頁、中間頁、尾頁的時間。
??? XCode開發(fā)模式非常看重分頁,基本上所有集合查詢方法都帶有分頁參數(shù)。Entity層只負責生成獲取滿足條件的所有數(shù)據(jù)的SQL,加上分頁參數(shù)后傳遞給下層數(shù)據(jù)訪問層,自身不處理問題。數(shù)據(jù)訪問層調(diào)用IDatabase接口的PageSplit方法,把上述的SQL處理為只獲取指定頁的SQL,然后再執(zhí)行查詢操作。因為不同的數(shù)據(jù)庫分頁方法不同,所以XCode的這種架構(gòu)讓使用者無需關心采用哪一種分頁方法。測試環(huán)境是SQL2008,所以自動采用row_number分頁。
?
??? 首先建立數(shù)據(jù)表
代碼 CREATE ? TABLE ? [ dbo ] . [ test ] (???? [ ID ] ? [ int ] ? IDENTITY ( 1 , 1 )? NOT ? NULL ,
???? [ HPHM ] ? [ varchar ] ( 50 )? NULL ,
???? [ JGSJ ] ? [ datetime ] ? NOT ? NULL ,
? CONSTRAINT ? [ PK_CLTXJL ] ? PRIMARY ? KEY ? CLUSTERED ?
(
???? [ ID ] ? DESC
) WITH ?(PAD_INDEX?? = ? OFF ,?STATISTICS_NORECOMPUTE?? = ? OFF ,?IGNORE_DUP_KEY? = ? OFF ,?ALLOW_ROW_LOCKS?? = ? ON ,?ALLOW_PAGE_LOCKS?? = ? ON )? ON ? [ PRIMARY ]
)? ON ? [ PRIMARY ]
?
???? 使用SQL語句插入一千萬行數(shù)據(jù)
declare ? @i ? intset ? @i = 0
while ? @i < 100
begin
insert ? into ?test? values ( ' 鄂A94450 ' , getdate ())
insert ? into ?test? values ( ' 鄂A92355 ' , getdate ())
(這里是更多數(shù)據(jù)插入語句)
set ? @i = @i + 1
end
GO
?
??? 最后是這種樣子
??? 再看看我們準備的測試代碼
測試代碼 static ? void ?Test2()
{
????Stopwatch?sw? = ? new ?Stopwatch();
????sw.Start();
????Console.WriteLine();
????DAL.AddConnStr( " Center " ,? " Data?Source=.;Initial?Catalog=Center;User?ID=sa;Password=Pass@word " ,? null ,? " sql2008 " );
????IEntityOperate?factory? = ?DAL.Create( " Center " ).CreateOperate( " test " );
????sw.Stop();
????Console.WriteLine( " 初始化:{0} " ,?sw.Elapsed);
????ICollection?list? = ?factory.FindAll( null ,? null ,? null ,? 100000 ,? 1 );
????DateTime?dt? = ?DateTime.Now;
???? foreach ?(IEntity?item? in ?list)
????{
????????dt? = ?(DateTime)item[ " JGSJ " ];
???????? break ;
????}
???? // String?where?=?String.Format("{0}>='{1}'?And?{0}<'{2}'",?"JGSJ",?dt,?dt.AddSeconds(100));
????String? where ? = ?String.Empty;
????sw.Reset();
????sw.Start();
????Console.WriteLine();
????Int32?count? = ?factory.FindCount( where ,? null ,? null ,? 0 ,? 0 );
????sw.Stop();
????Console.WriteLine( " 查詢總記錄數(shù):{0} " ,?sw.Elapsed);
????Console.WriteLine( " 總記錄數(shù):{0} " ,?count);
????Test2_0(sw,? " 默認順序 " ,?count,? where ,? null );
????Test2_0(sw,? " 時間升序 " ,?count,? where ,? " JGSJ?Asc " );
????Test2_0(sw,? " 時間降序 " ,?count,? where ,? " JGSJ?Desc " );
}
/// ?
/// ?測試用例
/// ?
/// ? 計時器
/// ? 標題
/// ? 總記錄數(shù)
/// ? 條件字句
/// ? 排序字句
static ? void ?Test2_0(Stopwatch?sw,?String?title,?Int32?count,?String? where ,?String?order)
{
????Console.WriteLine();
????Console.WriteLine( " {0}: " ,?title);
????IEntityOperate?factory? = ?DAL.Create( " Center " ).CreateOperate( " test " );
????sw.Reset();
????sw.Start();
????Console.WriteLine();
????ICollection?list? = ?factory.FindAll( where ,?order,? null ,? 0 ,? 10 );
????sw.Stop();
????Console.WriteLine( " 查詢前10行:{0} " ,?sw.Elapsed);
????sw.Reset();
????sw.Start();
????Console.WriteLine();
????list? = ?factory.FindAll( where ,?order,? null ,?count? / ? 2 ,? 10 );
????sw.Stop();
????Console.WriteLine( " 中間10行({1}):{0} " ,?sw.Elapsed,?count? / ? 2 );
????sw.Reset();
????sw.Start();
????Console.WriteLine();
????list? = ?factory.FindAll( where ,?order,? null ,?count? - ? 10 ,? 10 );
????sw.Stop();
????Console.WriteLine( " 最后10行({1}):{0} " ,?sw.Elapsed,?count? - ? 10 );
}
?
??? 上面第一個方法是控制方法,用來控制測試用例的。第二個方法就是測試用例了。
??? 在這里不得不提的是,第一個方法使用了最新版本V5.0的新特性——弱類型訪問。上一篇《動手》中提到,使用XCode首先需要利用代碼生成器生成實體類代碼,或者手工編寫,反正是需要實體類代碼,而本文只是為了測試,不需要那么復雜。動態(tài)添加一個連接字符串Center,并創(chuàng)建數(shù)據(jù)表test的操作接口,后面就可以利用這個操作接口去查詢數(shù)據(jù)了。弱類型訪問這一塊后面會專門介紹。
??? 第二個方法有三次查詢,分別是首頁、中間頁和尾頁。
??? 先來看看“默認順序”,其實就是ID降序
??? 因為數(shù)據(jù)表默認為自增ID建立聚集索引,所以在ID字段上的分頁查詢是最快的,首頁才3毫秒,中間頁也才4.5秒。
這里有必要說一下尾頁,這里不是作弊,而是XCode的一個小手段。在實際應用分頁查詢的時候,往往是越往后越慢,但只要把數(shù)據(jù)倒過來查,ID降序的尾頁其實就是ID升序的首頁,結(jié)果行集一致,只不過這10行數(shù)據(jù)是倒過來的,XCode在最后返回實體集合的時候會把它倒過來,就成了ID降序了。所以,在XCode查詢中,中間頁以后的頁都是反向查詢,中間頁是最慢的。
??? 接著看看“時間升序”
??? 首頁和尾頁5秒,中間頁17秒,很糟糕!看一下它們的執(zhí)行計劃
??? 習慣性的先看總開銷,三條語句居然是平分秋色,執(zhí)行時間一致!這個我就無法解釋了。
??? 從執(zhí)行計劃可以看到,95%的開銷都在于排序
??? 看詳情,原來是對JGSJ的排序造成的。看來應該為JGSJ建立索引。
??? 最后的這個“時間降序”,時間跟“時間升序”差不多,原理也一樣,就不分析了。
??? 上次第一輪測試看到,沒有索引,實在杯具!下面我們給JGSJ字段加上索引,繼續(xù)測試
??? 有了明顯變化,首頁和尾頁足夠快了,中間頁也變快了,但是還是偏慢,怎么回事?從執(zhí)行計劃看到,99%的時間都在于鍵查找
??? 原來是查找對應的HPHM,也是,索引只負責時間字段,而HPHM字段還是需要做全表掃描找出來的。在索引里面包含它試試
CREATE ? NONCLUSTERED ? INDEX ?IX_test_1? ON ?dbo.test(
??JGSJ
)
include?(HPHM)
WITH (?STATISTICS_NORECOMPUTE? = ? OFF ,?IGNORE_DUP_KEY? = ? OFF ,?ALLOW_ROW_LOCKS? = ? ON ,?ALLOW_PAGE_LOCKS? = ? ON )? ON ? [ PRIMARY ]
?
??? 再次測試
??? 漂亮!結(jié)果跟ID自增字段一樣。
??? 綜合上面的測試,最慢的中間頁能保持在5秒以內(nèi),算是一個不錯的成績了。不過這不能完全算是XCode的功勞,XCode僅僅是生成了分頁語句而已。而建立索引的建議,則是XCode開發(fā)模式的范疇。
?
??? XCode開發(fā)模式建議:每個表使用自增ID作為主鍵,獨享聚集索引。在數(shù)據(jù)分頁上,沒有比自增ID加上聚集索引更快的了,所以要把最好的留給它。業(yè)務主鍵還有經(jīng)常查詢的字段,根據(jù)情況建立非聚集索引。在千萬數(shù)據(jù)下,沒有索引的字段,基本上查不動。
??? 建立索引時,特別注意包含字段include(不是組合索引)。比如為時間字段建立了索引,根據(jù)時間字段查詢的時候,掃描索引字段會很快,但是掃描之后絕大部分時間都花在查找時間字段對應的車牌字段上了,如果建立時間字段索引的時候,把車牌字段include進去,就相當于在索引目錄里面就擁有了車牌信息,直接省去了對應車牌這一步,查詢性能將會得到非常大的提高。當然,include也是有代價的,添刪改操作會比原來慢,并且要占用更大的存儲空間。不過現(xiàn)在硬盤那么便宜,存儲空間問題不會太大,至于添刪改操作慢多少,就看業(yè)務來衡量了,一般可以接受。
??? 在SQLServer管理工具里面建立索引時,似乎無法添加include字段。可以先設置好索引,不要保存,點擊生成腳本,然后復制到查詢窗口,增加include后再執(zhí)行。
?
??? 前面的測試,都是簡單的沒有查詢條件的測試,下面我們試試帶查詢條件的測試
??? 屏幕一閃而過,就這樣完了!圖中看到,符合條件的數(shù)據(jù)共有2317+10=2327條,在這么小的數(shù)據(jù)量里進行分頁查詢,那速度,自然沒得說!
??? 在實際應用中,很少有需要查詢那么多頁的,百度、谷歌和淘寶等大型網(wǎng)站,最多也就返回前面一百頁。并且,業(yè)務系統(tǒng)一般有很多查詢條件,比如時間段等,經(jīng)過這些條件過濾,即使是千萬數(shù)據(jù)的表,也不會有太多滿足條件的數(shù)據(jù)。
?
這一切,XCode已經(jīng)為你準備!
?
大石頭
新生命開發(fā)團隊
2010-09-07 03:57
?
組件文檔打包下載(1~6)
作者: 大石頭 發(fā)表于 2010-09-15 23:28 原文鏈接
評論: 23 查看評論 發(fā)表評論
最新新聞:
· 是否該讓開發(fā)人員跟客戶直接交流?(2010-12-21 07:53)
· 亞馬遜副總裁跳槽Groupon任CFO(2010-12-21 07:50)
· Gmail語音服務將延長至2011年底(2010-12-21 07:49)
· AOL收購個人檔案網(wǎng)站About.me(2010-12-21 07:48)
· AT&T 19.25億美元購入高通 700MHz 低頻頻譜(2010-12-21 07:42)
編輯推薦:Mono又更新了
網(wǎng)站導航:博客園首頁??我的園子??新聞??閃存??小組??博問??知識庫
轉(zhuǎn)載于:https://my.oschina.net/nnhy/blog/11368
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的6,ORM组件XCode(撬动千万级数据)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Silverlight杂记-控件相关
- 下一篇: 通过FxCop来验证.NET编码规范