文本儲存,這是一個我以前很少去實施具體應用的領域。
何以會說起文本資料庫,從上篇:秋色園QBlog技術原理解析:效能最佳化篇:讀寫分離與文本資料庫(十八) 中,看出是出於應用,故而有幾許衝動。
當然地,從上文中,可以看出:基本基於文本的簡單的讀寫應用,輕輕地嚴格地一點地來說和“資料庫”不太著邊,境界不夠。
我想象中“文本資料庫”,再怎麼簡單,也得應該有以下幾個的吧:
1:有儲存結構[表結構]
2:有主鍵ID,不是GUID時,咋也得整個自增ID吧(大夥的應用習慣)。
3:能添加,修改,刪除資料。
4:最好還能查詢,排序,分頁,至於分組可能要求高了點。
5:再最好有並發控制。
回頭再看秋色園 QBlog 當前的應用是:
1:文本儲存的內容少:1個文本存的不是表,基本是1行(偶爾多行)。
2:基於第1點,只能說是文本的讀取應用,和“資料庫”還扯不上關係。
故從以上目前的應用來說,完全達不到文本資料庫應用的境界。
當然,有了基於文本的應用,故而順理成章的對文本擴充出的“文本資料庫”產生了些許興趣與衝動也就很自然了。
於是,我上網搜了一下“文本資料庫”,發現.net界幾乎沒有它的身影,倒是曾在php界大放過異采,這是為什麼呢?
這是為什麼呢?估計是為了以下內容:
用文本當資料庫的基本優勢:
1:簡單的文本操作速度比資料庫快:
非要解釋,我只能這麼說:大夥都存的磁碟,直接存肯定比資料庫繞了一定的儲存結構規則後存的快,當然越往後越複雜,就不好說了。
2:存取操作簡單:
不用啥ADO.NET,直接System.IO.File就可以搞定,多省事啊!
用文本當資料庫的基本劣勢:
1:資料量不適合大。
2:並發似乎不太好
3:刪除與修改不好操作
4:要變身成“文本資料庫”有好多要事要處理:
a:這自增加ID咋出來啊?
b:這要查詢咋整啊?
c:這要排序咋整啊?
用文本資料庫的基本適用的應用情境:
1:小型應用,以文本為主要資料庫:
單個(表)文本資料量不大:10萬條資料以下,10M大小以下(一次性載入到記憶體中操作,就成了記憶體資料庫了,速度嘩啦啦)。
2:大型應用,以文本為輔資料庫:
通過將一些資料庫分散到零散的文本中,降低主要資料庫的壓力。
3:中型應用,以文本為主要資料庫:
這個不好說,說不好,不說好,需要有一定強力的技術陣容支援。
為了更好的發揮“文本資料庫”的能動性,本人花了些時間對其進行了些許研究及思考,下面和大夥分享一下經驗:
1:儲存結構
這個我從秋色園 QBlog 的文本應用中得到提示,存成json,挺好的呀,這不json都流行的麼,直接讀取傳到前端,愛幹啥幹啥!
所以這裡的技術點是:如何輸出json和讀取json解析。
這裡:CYQ.Data V3.0 架構開源版本(下載)裡有一個JsonHelper,能把資料產生Json,也能把json字串解析成KeyValue索引值對應,感興趣的可去研究。
於是,基本讀與取就解決了。
2:資料插入
使用:System.IO.File.AppendAllText就可以輕鬆把一行的json加到文本的末尾中。
3:更新、刪除
這兩個操作幾乎是差不多,個人想到的兩種方式:
方式一:簡單型 [這個其實挺好,因此從文本資料庫的應用情境上看,基本要求並不是太高]
將整個表的重新輸出json,再重寫一次文本就可以了。
方式二:複雜型[這個是效能考慮的多一些,對於文本資料庫追求的過些過了一點,因為如果太複雜,何不找其它資料庫,用文本不就圖個簡單麼]
這個比較痛苦,這裡也給出一點個人的思路想法:
1:定表結構時,必須定好每個欄位的長度,這樣就定出一行總的最大長度。
2:寫一行資料時,不夠總長時,後面補空(好像通常是寫入\0)。
3:更新或刪除時,根據行的(ID-1)*總長,定位到起始寫的位置,然後改寫一行即可,如果是刪除則當行全寫空(\0)。
這裡其實就是空間換時間,而且資料刪除時,文字大小也沒變化,是不是有點像access呢?
針以上面方式二,這裡給出點範例程式碼:
FileStream fs = File.Open(檔案路徑);
fs.Seek(定位要寫入的開始位置, SeekOrigin.Current);
fs.Write(..寫入內容...);
fs.Close();
4:自增ID咋出來
增加ID還是比較容易,讀取文本最後一行的首欄位的值+1就出來了,當然僅適合於數字型的了,然後全域緩衝,每次讀取++。
下面給出一個參考的範例程式碼:
/// <summary>
/// 下一個自增加ID
/// </summary>
private int NextID
{
get
{
lock (lockNextIDobj)
{
if (maxID > 0)
{
maxID++;
}
else if (DataType.GetGroupID(Table.Columns[0].SqlType) == 1)//自增ID僅對int有效
{
if (Table.Rows.Count > 0)
{
int lastIndex = _Table.Rows.Count - 1;
do
{
if (lastIndex >= 0)
{
if (_Table.Rows[lastIndex][0].IsNull)
{
lastIndex--;
}
else
{
maxID = Convert.ToInt32(_Table.Rows[lastIndex][0].Value) + 1;
}
}
else
{
maxID = 1;
}
}
while (maxID == 0);
}
else
{
maxID = 1;
}
}
else
{
throw new Exception("Increment id only use for int type");
}
}
return maxID;
}
}
5:查詢怎麼辦
其實這個很好辦,將json解析還原為數組列表之後,數組有個FindAll方法,搜點教程研究一下就可以了,對於數組的查詢,園子裡還是有不少文章介紹的。
6:排序怎麼辦
這個也很好辦,同樣json解析還原為數組列表之後,數組有個Sort方法,同樣搜點教程就可以了。
7:單進程並發怎麼控制
這個其實也好辦,加lock鎖就行了。
8:多進程並發怎麼控制
在IIS應用程式集區回收或啟用多個exe程式時,多進程可能出現同時操作文本資料庫的情況,這裡我也思考了良久,怎麼去控制?
最後我想出來的方式是:進程在準備更改文本時,讀取文本最後修改時間進行比對,進而達到一種相對控制。
總結:
個人覺得解決完上面的問題之後,基本簡單的文本資料庫也成型了,當然你也可以往上繼續追求。
不過文本資料庫,折騰的太複雜也沒必要,畢竟文本資料庫,還是以簡單為主。
如果NoSql會流行,何不讓文本資料庫也在.net界也出出風頭,成長成.Net界的一朵奇葩!