被網(wǎng)上小將們罵怕了。但是該寫(xiě)還是要寫(xiě),而且堅持原創(chuàng )繼續毀人不倦。我們的口號是(沒(méi)有蛀牙?。。。?/span>
本垃圾文章描述了一種類(lèi)似于緩存的查詢(xún)方式,將數據放入內存中進(jìn)行查詢(xún),從而達到提高響應速度增加吞吐量的目的。方法簡(jiǎn)單,屬于原創(chuàng )。缺點(diǎn)等待大家來(lái)評論。
本文技術(shù)內容其實(shí)很簡(jiǎn)單,但是我前邊會(huì )寫(xiě)一些技術(shù)之外的東西,因為不僅在中國就是在世界上很多東西比技術(shù)更重要。畢竟技術(shù)是為了更好的提供服務(wù)。往往是最末的一環(huán),請各位程序員和準程序員清醒這一點(diǎn)。另外還簡(jiǎn)單介紹了設計的過(guò)程歡迎有同樣小型項目管理經(jīng)驗的同道評論,也給初學(xué)者參考。
正文開(kāi)始:
之前我們參考了南方兄弟招辦已有系統(運行過(guò)一年,我們本來(lái)想去年搞,但是沒(méi)搞起來(lái),人家先做了)地運行情況。算是學(xué)習了經(jīng)驗。最后我們認為整個(gè)系統的壓力應當集中在填報志愿過(guò)程中(廢話(huà))。
填報方案選型過(guò)程:
一、如果考生直接選擇院校名稱(chēng)和專(zhuān)業(yè)的話(huà),對服務(wù)器和網(wǎng)絡(luò )壓力太大,該方案淘汰。(在后期征集志愿時(shí)由于院校數目少可以考慮)
二、志愿翻譯:簡(jiǎn)單說(shuō)來(lái)就是:考生輸入報考院校的學(xué)校代號和專(zhuān)業(yè)代號,然后系統翻譯為現實(shí)的名稱(chēng),考生檢查是否正確即可。
例如10003:01,02 翻譯為:清華大學(xué):工程力學(xué)與航天航空工程,藝術(shù)設計學(xué)。
選擇:方案二,考生填寫(xiě)代碼,系統翻譯志愿。
設計實(shí)現過(guò)程
設計目標:
翻譯過(guò)程很簡(jiǎn)單但是主要是次數比較多。每位考生一次填寫(xiě)正確需要翻譯9批次*2-5院校*1院校名稱(chēng)+6專(zhuān)業(yè)名稱(chēng)=250次左右的翻譯。共55萬(wàn)考生。一共需要翻譯1.25億次。平均到2天的工作時(shí)間16小時(shí),平均每秒翻譯2170次。再用正態(tài)分布估算。我們覺(jué)得每秒1萬(wàn)次翻譯作為設計目標應當能夠滿(mǎn)足實(shí)際應用的情況。
說(shuō)起來(lái)簡(jiǎn)單,實(shí)際上每個(gè)學(xué)校翻譯的時(shí)候還需要判斷科類(lèi)、考生類(lèi)別、限報條件等,所以sql查詢(xún)語(yǔ)句效率不會(huì )太高。
翻譯方案選型:
一、Sql存儲過(guò)程
已有系統的查詢(xún)使用存儲過(guò)程來(lái)完成查詢(xún),將web服務(wù)器和數據庫服務(wù)器之間的通信減到最小。然后通過(guò)對數據庫進(jìn)行優(yōu)化將性能最大化。
這種方法比較成熟,也是大家首先能夠想到的,實(shí)施起來(lái)風(fēng)險也較小,數據流量也可很容易的分布到多個(gè)數據庫上(不要給我提什么群集,挖掘一類(lèi)的,我們有2臺F5,根本不需要那么麻煩再爛的系統也能夠運行的差不多。但是不能那樣做事。第一設備再先進(jìn),也要你的底層架構設計合理才可以。第二、設備技術(shù)再先進(jìn)是人家微軟、IBM的又不是自己的,要想進(jìn)步,要自己去努力。我實(shí)在不明白為什么有些人使用起那些名詞來(lái)那么理直氣壯好像是自己發(fā)明的一般。)
為了規避風(fēng)險我們首先實(shí)現了該方法,但是并沒(méi)有在數據優(yōu)化時(shí)下功夫因為我們認為,這種方法效率不高。比如:我們僅僅是只讀的查詢(xún)。一共的3萬(wàn)記錄進(jìn)行1.25億次查詢(xún)相當于每條平均查重復4000多次,這是巨大的性能浪費。
而且sql查詢(xún)時(shí)作負載均衡我們嫌麻煩,我們這時(shí)就是想要試驗去做一種沒(méi)有試過(guò)的高效的內存查詢(xún)算法??纯吹降啄芤龆嗌傩阅軄?lái)
二、專(zhuān)有數據庫查詢(xún):實(shí)際上無(wú)論是平易近人的mssql還是走下神壇的ORCAL由于太大,求全涉及到方方面面。他的數據查詢(xún)效率并不如專(zhuān)有數據庫效率高。就像CE不如PALM快,雖然PALM不先進(jìn)但是運行快。但是時(shí)間長(cháng)了,由于CE的通用性和兼容性還是占據了比較大的市場(chǎng)。
但是專(zhuān)有的數據庫用起來(lái)一方面技術(shù)比較冷門(mén),另外我們沒(méi)有時(shí)間去進(jìn)行評估也就無(wú)法去選擇。單獨為一個(gè)系統去學(xué)習一個(gè)冷門(mén)數據庫不劃算。
三、內存數據庫,目前內存數據庫上網(wǎng)查了查有一個(gè)韓國的廠(chǎng)商在工控領(lǐng)域做的不錯。另外好像微軟的Microsoft SQL Server 2005 Compact Edition
(這個(gè)不確認是內存的,但是好像支持,而且好像對多用戶(hù)支持不好或不支持)做的也不錯。感興趣的去這個(gè)地址:http://www.microsoft.com/downloads/details.aspx?FamilyId=E6BC81E8-175B-46EA-86A0-C9DACAA84C85&displaylang=en#filelist
四、私有算法。我們最后選擇了自動(dòng)開(kāi)發(fā)一種查詢(xún)算法。因為:
1、 創(chuàng )新的需求。做東西技術(shù)人員總要有所追求創(chuàng )新,有個(gè)東西是你自己的,總是用別人的有啥意思?
2、 我們的查詢(xún)比較簡(jiǎn)單,沒(méi)有必要實(shí)現到數據庫的層次。為了我們簡(jiǎn)單的查詢(xún),沒(méi)有必要去實(shí)現Codd十二法則?這樣我們就可以借著(zhù)這個(gè)項目研究新技術(shù),同時(shí)還可以控制風(fēng)險。
3、 時(shí)間充裕:我們設計完之后,用2天就實(shí)現了基于內存查詢(xún)的并進(jìn)行了評估(雖然網(wǎng)上沒(méi)有現成的,但是只要想到了確實(shí)很簡(jiǎn)單,就和原來(lái)我們寫(xiě)漢字字庫實(shí)際上一樣),結論是值得一試。
具體實(shí)現:(請注意本文的實(shí)現與現實(shí)嚴格關(guān)聯(lián),因為實(shí)際工作中這些政策年年變,不可能復用,所以也就沒(méi)有完全面向對象,而只是抽了出來(lái)做成類(lèi)方便維護而已。)
系統具體實(shí)現部分
系統實(shí)現的原理:
原理很簡(jiǎn)單將數據放入數組或哈希表中,然后查找即可,關(guān)鍵是如何實(shí)現。
關(guān)鍵在于:
第一、 如何將表放入內存中。
第二、 如何對外提供查詢(xún)。
對于第一個(gè)問(wèn)題我們可以很簡(jiǎn)單的通過(guò)將數組和哈希定義為靜態(tài)變量從而常駐內存。
請原諒我的代碼中有拼音因為。。。教育部的表就是拼音縮寫(xiě)的,因為廣大招辦有很多老同志,都換成英文不可能。
public static string[,] stryxs = new string[3200, 4];//前邊是學(xué)校數,后邊是每組結構 學(xué)校名稱(chēng)+kldm+pc+zsfw 科類(lèi)代碼、批次、招生范圍
public static Hashtable htzys = new Hashtable();
然后在構造函數中填充數據例如:
///首先加載院校代碼表 jihuas dsjihua = new jihuas();
jihuasTableAdapters.tjhyxTableAdapter jhapt = new jihuasTableAdapters.tjhyxTableAdapter();
//將指定院校(YXBM從01開(kāi)始排)放入數組
foreach(jihuas.tjhyxRow dr in dsjihua.tjhyx)
{
//填充數據
}
然后在全局文件Global.asax中將該類(lèi)實(shí)例化即可
void Application_Start(object sender, EventArgs e)
{
// 在應用程序啟動(dòng)時(shí)運行的代碼
cache ap = new cache();//加載全局類(lèi)
}
對于第二個(gè)問(wèn)題,就好說(shuō)多了,有了數據,查詢(xún)、就是了。。
好了不說(shuō)廢話(huà),看程序。。
系統代碼實(shí)現:
///本模塊功能是:
///1、構建全局緩存,在全局緩存中構建鍵列,供志愿查找使用
///2、提供刷新全局緩存功能。(調用構造函數)
///構建全局緩存,應用一次構造函數即可
///提供的全局緩存包括
///1、志愿:院校、專(zhuān)業(yè)名稱(chēng)
///2、區域對照表:地市、縣區、報名點(diǎn)代碼對照表using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Text;
using System.Text.RegularExpressions;
/// <summary>
/// cachetest 的摘要說(shuō)明
/// </summary>public class cache
{
//str??? 代表字符串數組 ht???代表哈希表
//public static ArrayList alyxs=new ArrayList ();//測試中使用過(guò)的方式
public static string[,] stryxs = new string[3200, 4];
///前邊是學(xué)校數,后邊是每組結構 學(xué)校名稱(chēng)+kldm+pc+zsfw共4項,
///其中學(xué)校編碼為從0001開(kāi)始的4位編碼,正好作為數組的下表stryxs[1]=0001院校的數據
public static Hashtable htzys = new Hashtable();///志愿表
public static Hashtable htdishi = new Hashtable();///地市
public static Hashtable htxq = new Hashtable();///縣區
public static Hashtable htbmd = new Hashtable();///報名點(diǎn)
/// <summary>
/// 構造函數,加載緩存
/// </summary>
public cache()
{
///首先加載院校代碼表
jihuas dsjihua = new jihuas();
jihuasTableAdapters.tjhyxTableAdapter jhapt = new jihuasTableAdapters.tjhyxTableAdapter();
jhapt.Fill(dsjihua.tjhyx);
///沒(méi)有0院校,需要處理一下
stryxs[0, 0] = "院校填寫(xiě)錯誤";
stryxs[0, 1] = "";
//將指定院校(YXBM從01開(kāi)始排)放入數組
foreach(jihuas.tjhyxRow dr in dsjihua.tjhyx)
{
int yxbm = Convert.ToInt16(dr.YXBM);
///07年有一個(gè)院校 編號為9001,將其轉化為3199,后來(lái)臨時(shí)加的,
///各部門(mén)沒(méi)有協(xié)調好以至于編號從9001開(kāi)始,其實(shí)要是使用3200以?xún)乳e置的代碼號就不用這樣處理了
///再有新增的也這樣處理。
if (yxbm == 9001)
{
yxbm = 3199;
}
stryxs[yxbm, 0] = dr.YXMC.Trim();
//累加該院校的kldm
//此處沒(méi)有判斷科類(lèi)是否會(huì )重復,不需要判斷,重復不影響例如AABBCCDD,只要有即可。此處可以改用STRINGBULIDER,
string kldm = stryxs[yxbm, 1];
string newkldm=dr.KLDM.Trim();
kldm = kldm + newkldm;
stryxs[yxbm, 1] = kldm;
//累加該院校的pc省略
//記錄招生范圍省略
}
//加載專(zhuān)業(yè)代碼表
///SELECT DISTINCT yxbm, yxmc, jhxz, kldm, pc, cc
///ORDER BY yxbm
jihuasTableAdapters.tjhzyTableAdapter zyapt = new jihuasTableAdapters.tjhzyTableAdapter();
zyapt.Fill(dsjihua.tjhzy);
foreach (jihuas.tjhzyRow dr in dsjihua.tjhzy)
{
///追加的hash表格式為 keys 專(zhuān)業(yè)名稱(chēng)
///其中keys 為 yxbm+ZYBM+kldm+pc
///使用keys查找
htzys.Add(dr.YXBM.Trim() + dr.ZYBM.Trim()+dr.KLDM.Trim()+dr.PC.Trim(), dr.ZYMC);
}
///SELECT YXBM, ZYBM, zymc, jhxz, KLDM, pc, cc
///ORDER BY jhxz, KLDM, pc, cc, YXBM, ZYBM
//加載報名點(diǎn)代碼
jihuasTableAdapters.baomingdianTableAdapter bmdapt = new jihuasTableAdapters.baomingdianTableAdapter();
bmdapt.Fill(dsjihua.baomingdian);
foreach (jihuas.baomingdianRow dr in dsjihua.baomingdian)
{
///追加的hash表格式為 keys 報名點(diǎn)名稱(chēng)
///其中keys 為 dmddm
htbmd.Add(dr.ZXDM.ToString().Substring(1,6), dr.ZXMC.ToString().Trim());
}
//加載區縣代碼
jihuasTableAdapters.td_xqdmTableAdapter xqdapt = new jihuasTableAdapters.td_xqdmTableAdapter();
xqdapt.Fill(dsjihua.td_xqdm);
foreach (jihuas.td_xqdmRow dr in dsjihua.td_xqdm)
{
///追加的hash表格式為 keys 縣區名稱(chēng)
///其中keys 為 xqdm
htxq.Add(dr.xqdm.ToString().Substring(1,4), dr.xqmc.ToString().Trim());
}
//加載地市代碼
jihuasTableAdapters.td_dsdmTableAdapter dsdapt = new jihuasTableAdapters.td_dsdmTableAdapter();
dsdapt.Fill(dsjihua.td_dsdm);
foreach (jihuas.td_dsdmRow dr in dsjihua.td_dsdm)
{
///追加的hash表格式為 keys 地市名稱(chēng)
///其中keys 為 dsdm
htdishi.Add(dr.dsdm.ToString().Substring(1, 2), dr.dsmc.ToString().Trim());
}
}
//將數據表讀入緩存中。然后使用
/// <summary>
/// 志愿轉換
/// </summary>
/// <param name="zyxx">志愿信息</param>
/// 序號 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/// 有效 yxdh zydh1 zydh2 zydh3 zydh4 zydh5 zydh6 tj laiyuan ksh pcdm zyh zyhanyi tiaoji validstr bmddm kldm
/// <returns></returns>
public static string tranzhiyuan(ArrayList zyxx)
{
///翻譯步驟
///1、檢查翻譯合法性,是否能夠找到(還未考慮)
///2、翻譯院校名稱(chēng)
///3、翻譯專(zhuān)業(yè)名稱(chēng)
///4、翻譯調劑
///
//檢查cache是否存在
if (!cache.testcache())
{
return "錯誤!請聯(lián)系系統管理員,重新啟動(dòng)應用程序以加載系統緩存!";
}
StringBuilder retstr = new StringBuilder();
retstr.Append("");
//首先判斷院校編號是否填寫(xiě),并且不越界
//07年有一個(gè)院校編號為9001放入了3199需要處理與前邊呼應,被臨時(shí)變動(dòng)打亂了
if (zyxx[0].ToString().Trim() == "9001")
{
zyxx[0]= "3199";
}
if (zyxx[0].ToString().Trim() == "")
{
retstr.Append("未填寫(xiě)志愿!");
return retstr.ToString();
}
if (!cache.IsNumeric(zyxx[0].ToString().Trim()))
{
retstr.Append("錯誤輸入!必須是數字!");
return retstr.ToString();
}
if (zyxx[0].ToString().Trim().Length != 4)
{
retstr.Append("錯誤輸入!院校是4位數字!");
return retstr.ToString();
}
if ((Convert.ToInt16(zyxx[0].ToString().Trim()) < 3200))
{
//首先需要取出院校編碼,判斷院校編碼的范圍,可能超出,如果超出,則返回院校代碼錯誤,
//然后判斷該院校是否有所填科類(lèi),返回院校沒(méi)有符合條件的科類(lèi)
int yxdh = Convert.ToInt16(zyxx[0].ToString().Trim());
string yxmc = stryxs[yxdh, 0].Trim();
//處理錯誤院校,該錯誤為院校編號不連續,用戶(hù)可能恰巧輸入錯誤的編號,錯誤編號返回值應為null。另外長(cháng)度也需要檢查
if (yxmc != null)
{
if (yxmc.Length < 2)
{
retstr.Append("無(wú)此院校,必須是招生計劃中的正確院校編號");
return retstr.ToString();
}
}
else
{
retstr.Append("無(wú)此院校,必須是招生計劃中的正確院校編號");
return retstr.ToString();
}
//已有的院校,需要判斷pc和KLDM
string pcs = stryxs[yxdh, 2].Trim();
string kldms = stryxs[yxdh, 1].Trim();
if (pcs.IndexOf(zyxx[10].ToString().Trim()) == -1)
{
retstr.Append("無(wú)此院校,批次錯");
return retstr.ToString();
}
if (kldms.IndexOf(zyxx[16].ToString().Trim()) == -1)
{
retstr.Append("無(wú)此院校,報考科類(lèi)錯");
return retstr.ToString();
}
//判斷招生范圍 專(zhuān)業(yè)術(shù)語(yǔ)部分不用考慮含義
if ((stryxs[yxdh, 3].Trim() != "0") && (stryxs[yxdh, 3].Trim() != "81") && (stryxs[yxdh, 3].Trim() != "82")&&(stryxs[yxdh, 3].Trim() != "83"))
{
if (stryxs[yxdh, 3].ToString().Replace("0","").Trim()!="")//有時(shí)可能會(huì )有多個(gè)0,所以不能REMOVE
{
if (zyxx[9].ToString().Trim().Substring(4, 2) != stryxs[yxdh, 3].Trim())
{
retstr.Append("無(wú)此院校,請檢查該院校招生范圍");
return retstr.ToString();
}
}
}
//都正確返回院校名稱(chēng)
retstr.Append(zyxx[0].ToString() + stryxs[yxdh, 0].Trim() + " ");
///***************************************************
///***************************************************
/// 下邊的進(jìn)程延遲語(yǔ)句發(fā)布時(shí)一定要去掉。在測試Ajax刷新效果時(shí)使用
///***************************************************
//////***************************************************
//System.Threading.Thread.Sleep(1000);//延遲??毫秒再返回
//開(kāi)始翻譯專(zhuān)業(yè)
for (int i = 1; i < 7; i++)
{//翻譯專(zhuān)業(yè):
//首先判斷是否為空
if (zyxx[i].ToString().Trim() != string.Empty)
{
//首先生成keys
///追加的hash表格式為 keys 專(zhuān)業(yè)名稱(chēng)
///其中keys 為 YXBM+ZYBM+kldm+pc
string key = zyxx[0].ToString().Trim() + zyxx[i].ToString().Trim() + zyxx[16].ToString().Trim() + zyxx[10].ToString().Trim();
if (htzys.Contains(key))
{
retstr.Append(zyxx[i].ToString() + htzys[key].ToString().Trim() + " ");
}
else
{//如果專(zhuān)業(yè)找不到
retstr.Append(zyxx[i].ToString().Trim() + "(無(wú)此專(zhuān)業(yè))" + " ");
}
}
else
{//此處else分支為只要有空白不再向下翻譯//已經(jīng)修改為空白也繼續翻譯,但是需要注意如果后邊還有數據才翻譯,如果后邊的都為空則不再翻譯
//if (zyxx[7].ToString() == "1")
//{ retstr.Append("服從分配"); }
//else { retstr.Append("不服從分配"); }
//return retstr.ToString();
bool transflag = false;
for (int j = i; j < 7; j++)//判斷該空位專(zhuān)業(yè)后邊是否還有專(zhuān)業(yè),有則翻譯為空白專(zhuān)業(yè),沒(méi)有則本條為最后一條空白專(zhuān)業(yè),不需要翻譯
{
if (zyxx[j].ToString().Trim() != string.Empty)
{
transflag = true;
}
}
if (transflag)
{ retstr.Append(zyxx[i].ToString() + "空白專(zhuān)業(yè)" + " "); }
}
}
//最后附加是否服從分配
if (zyxx[7].ToString() == "1")
{ retstr.Append("服從專(zhuān)業(yè)調劑"); }
else { retstr.Append("不服從專(zhuān)業(yè)調劑"); }
return retstr.ToString();
}
else
{
retstr.Append("無(wú)此院校,必須是招生計劃中的正確院校編號!");
return retstr.ToString();
}
// return retstr.ToString();
}
/// <summary>
/// 測試當前系統緩存是否存在
/// </summary>
/// <returns></returns>
private static bool testcache()
{
//僅僅是測試了一個(gè)表是否存在而已,要有都有,要沒(méi)都沒(méi),這里沒(méi)有用try因為每次查詢(xún)try系統消耗太大。而且如果表不存在,靜態(tài)方法也就不存在了。
if (htzys.Count > 0)
{ return true;}
else { return false; }
}
//從學(xué)院字符串數組中取值,調試用
public static string getyxs(int i)
{
return stryxs[i, 0] + stryxs[i, 1];
}
/// <summary>
/// 翻譯地市代碼
/// 傳入字符串代碼 返回結果
/// </summary>
/// <param name="dm"></param>
/// <returns></returns>
public static string transdsdm(string key)
{
if (htdishi.Contains(key))
{
return htdishi[key].ToString().Trim();
}
else
{//如果專(zhuān)業(yè)找不到
return "地市代碼錯誤!";
}
}
/// <summary>
/// 翻譯縣區代碼
/// 傳入字符串代碼 返回結果
/// </summary>
/// <param name="dm"></param>
/// <returns></returns>
public static string transxqdm(string key)
{
if (htxq.Contains(key))
{
return htxq[key].ToString().Trim();
}
else
{//如果專(zhuān)業(yè)找不到
return "縣區代碼錯誤!";
}
}
/// <summary>
/// 翻譯報名點(diǎn)代碼
/// 傳入字符串代碼 返回結果
/// </summary>
/// <param name="dm"></param>
/// <returns></returns>
public static string transbmddm(string key)
{
if (htbmd.Contains(key))
{
return htbmd[key].ToString().Trim();
}
else
{//如果專(zhuān)業(yè)找不到
return "報名點(diǎn)代碼錯誤!";
}
}
/// <summary>
/// 翻譯院校代碼
/// 傳入字符串代碼 返回結果
/// </summary>
/// <param name="dm"></param>
/// <returns></returns>
///public static string transyxdh(string key,string ksh,string pc)
public static string transyxdh(string hanyi)
{
///現在不再翻譯,直接取出含義字段中的翻譯
///過(guò)來(lái)的含義字段有2種格式,
///正確的10094河北師范大學(xué)
///錯誤的,無(wú)此院校,或報考。。。錯
string[] words=hanyi.Split(new char[]{' '});
if (words.Length >0)
{
//還需要判斷前4個(gè)字符是否是漢字。因為有可能只填寫(xiě)了學(xué)校。
string temp = words[0].ToString().Trim();
if(IsNumeric(temp.Substring(0,4)))
{
return temp.Substring(4, temp.Length - 4);
}
return words[0].ToString().Trim();
}
else
{
return "院校代碼格式未知!";
}
}
/// <summary>
/// 判斷是否是數字
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static bool IsNumeric(string str)
{
return Regex.IsMatch(str, @"^-?\d+(\.\d)?$");
}
/// <summary>
/// 將院校表輸出測試用
/// </summary>
public static string test()
{
StringBuilder strs = new StringBuilder();
for (int i = 0; i < 3200; i++)
{
string temp="";
try
{
temp = stryxs[i, 3].Trim();
}
catch
{ }
if (temp.Length != 2)
{
strs.Append(temp + "<br />");
}
}
return strs.ToString();
}
}
調用方式說(shuō)明:傳入的為一個(gè)ARRAYLIST 00001,01,02。。。。
string zhiyuanhanyi = cache.tranzhiyuan(zyxx);//翻譯志愿含義,并放在控件中顯示
tbxxdm.Text = zyxx[0].ToString();
tbzy1.Text = zyxx[1].ToString();
tbzy2.Text = zyxx[2].ToString();
tbzy3.Text = zyxx[3].ToString();
tbzy4.Text = zyxx[4].ToString();
tbzy5.Text = zyxx[5].ToString();
tbzy6.Text = zyxx[6].ToString();
終于完了,能夠看到這里的都是高手(沒(méi)有耐心成不了高手)。其實(shí)給出這么長(cháng)的代碼段并沒(méi)有必要,但是如果修改太多又需要時(shí)間太多,而且其中有一個(gè)修改的地方能夠很好的詮釋一些不在計劃中的意外的處理。所以就直接搬上來(lái)了。
原理很簡(jiǎn)單,實(shí)現也不麻煩。
實(shí)際效果很好,能夠實(shí)現每秒百萬(wàn)次級別的查詢(xún)。而且僅僅加載時(shí)訪(fǎng)問(wèn)數據庫。我想這可能是這種特殊環(huán)境下的最高效率了。
原因很簡(jiǎn)單:
第一、翻譯院校名稱(chēng)根本就沒(méi)有查找過(guò)程,直接下標訪(fǎng)問(wèn)的。
第二、翻譯專(zhuān)業(yè)名稱(chēng)時(shí)哈希表的算法復雜度與直接下標訪(fǎng)問(wèn)差不多(多一次計算hash值)
希望有人能夠告訴我有沒(méi)有更好更快得方法。我很感興趣。
我這里有負載評測本方法與數據庫查詢(xún)方法比較的測試數據(不使用存儲過(guò)程的未經(jīng)優(yōu)化的數據庫同樣查詢(xún)每秒300-1000次,性能保守快2個(gè)數量級以上。),改天整理一下再放上來(lái)。
反思:
1、 實(shí)現的缺陷,靜態(tài)方法支持多線(xiàn)程嗎?我不大好說(shuō),但是負載測試時(shí)確實(shí)4個(gè)cpu都跑起來(lái)了。盼望高人指點(diǎn)。
2、 該方法占用內存。我們加載了全部3萬(wàn)條記錄后,大概占用60m左右內存。當然對于現在我們動(dòng)輒4g以上的內存不算什么。
3、 不支持sql標準查詢(xún)。
4、 如果海量數據,內存盛不下如何操作?還有如何支持數據更新?我目前沒(méi)事的時(shí)候在研究這個(gè)。希望在用戶(hù)和數據庫中增加一個(gè)中間層作緩沖,從而進(jìn)一步提高數據庫吞吐量。作為高考數據量可能沒(méi)有這個(gè)必要,但是對性能的需求是無(wú)止境的。
5、 該方法使用起來(lái)可靠嗎?實(shí)際使用時(shí)沒(méi)有出現問(wèn)題,不知道有沒(méi)有高手指出可靠性的缺陷。
6、有沒(méi)有人能夠比較與.net新增的緩存的比較。