在PyCon上有童鞋提供了一個類似概念的分享,不過不大適合一般類型的互聯網項目,感覺有點過於另類。不過我實現這個方案是在看到PyCon的分享之前。算是同樣的訴求不同的實現方式吧。且我這裡只是實現了一個數據訪問的組件而不是Server。
首先本文的方法來自FriendFeed分享的如何使用MySQL數據庫的分享。簡而言之就是把Python對象直接dumps後zip壓縮存儲在MySQL一個字段裡。這樣不就Schemaless了麼?存什麼數據類型,類什麼結構,MySQL都不需要知道,加個屬性什麼的都不需要修改數據庫表結構,對於業務快速變更、快速增長的互聯網業務來說再合適不過了。訪問對象直接通過主鍵查詢,快速直接。but,查詢怎麼辦?有的童鞋可能會問。OK,查詢這事得分兩說,如果是簡單的檢索,可以通過建索引表的方式來解決,或者呢用外部的索引,比如lucent,還能全文檢索哦。現在而今眼目下我實現了索引表索引的方式,因為外部的索引方式比較千奇百怪,所以如果需要可以根據具體情況自己來寫一個,反正實現相應的幾個方法就行。
直接上一個例子來說明。假設要實現一個blog,需要存blog的信息,先定義一個blog的模型類(需要import什麼大家自動腦補)
Copy to Clipboard引用的內容:[www.bkjia.com] class Blog(DynamicBase):這個connection是因為我還沒想好如何能無縫結合到Django中又能兼顧脫離Django獨立使用的暫時措施,完成版會去掉
如果在使用django的話只需要 python manage.py shell 然後 Blog.objects.create_table()
這個時候會自動創建模型定義的表和索引表
數據表 blogs:
同時建立兩個索引表
CREATE TABLE `blog_idx_post_date` (
`id` int(10) unsigned NOT NULL,
`post_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_blogs_by_post_date` (`post_date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `blog_idx_auther` (
`id` int(10) unsigned NOT NULL,
`auther` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `idx_blogs_by_auther` (`auther`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這個時候,可以通過 Blog.objects.create(title=u"標題",content=u"內容",post_date=datetime.datetime.now(),auther=user) 或者Blog.objects.create(title=u"標題",content=u"內容",post_date=datetime.datetime.now(),auther=user.id)
就能夠創建一個Blog的對象。這個時候blogs表和兩個索引表都會插入數據。不過blogs表中的object列是人類無法理解的火星文..........
通過id直接獲取對象 Blog.objects.get(1),根據索引獲取 Blog.objects.auther.query(auther=user.id) 或者 Blog.objects.auther.query(auther=user)
這個會生成SQL,SELECT `id` FROM `blog_idx_auther` WHERE `auther`=%s 然後取出match到對象的id列表,然後遍歷id列表,通過 Blog.objects.get(id)獲得的對象列表。
Blog.objects.get(id)的時候是有對象緩存的(現階段通過redis實現),所以經過測試,速度是靠譜的。而相對MangoDB來說,MySQL的數據存儲也更加靠譜一點,所以相比換現在而今眼目下還不怎麼靠譜的mangodb來作為主存儲來說,基於MySQL的Schemaless方案還是相對靠譜的。
由於現在這個東西還是處於在項目中孵化的階段還沒有能夠達到可以獨立開源出來供大家娛樂的程度,所以請大家對這個方案多提意見建議咯,源代碼估計能夠在春節後達到能夠公布出來見人的階段。
(本文來源:懶人居 - Coding for fun)