以前三篇講了MoSonic總體設計上的思路參考。這篇講一下其中的一些細節優化方面遇到的問題。html
Cache Money對於查詢類型的要求限制的很是死,整個系統變成只有兩種查詢:sql
假設有user表,有password跟is_banned兩列。已知user_name,要如何得到is_banned?數據庫
Cache Money的限制使得必須得有兩個查詢:緩存
而後再從第二個查詢裏面的*去得到is_banned。服務器
有人會認爲這很傻,徹底能夠用一個: select is_banned from user where user_name=XXX的查詢來替代,實現減小sql查詢次數,以及sql返回的數量兩方面的優化。網絡
這是「優化」是一個頗有意思的問題。若是咱們要認爲 select is_banned from user where user_name=XXX 是一個優化;首先必須清楚瞭解這條sql中數據庫究竟作了什麼。併發
首先,要支持where user_name=XXX的查詢,user_name這列是必須加索引的。框架
那麼,user_name的索引中包含了什麼?這實質上是user_name對user表主鍵(id)的索引!分佈式
數據庫要返回is_banned這個數據,實際上它是須要:ide
上述的數據庫內部操做,跟cache money的兩個查詢實質上是一一對應的。
惟一不一樣的是,數據庫查詢是硬盤尋址,而cache money是memcache訪問。
memcache與傳統硬盤誰快?memcache與SSD硬盤誰快?一個memcache集羣與單個SSD物理硬盤誰快?高併發情景下又如何?
咱們的初衷是要實現一個分佈式的系統以解決性能問題,但爲何忽然又要把單個硬盤上的操做視爲一個優化?
有人還會認爲一開始user_name的索引其實建錯了,應該是建user_name + is_banned的聯合索引,這樣數據庫內部在執行select is_banned from user where user_name=XXX 這個查詢的時候,就能夠直接在索引數據上得到is_banned的值,而無需多一次尋址。
這種又是否是優化?
咱們先把user表的分佈式放一邊,僅考慮單機的狀況;咱們假設它是優化。
咱們原來的設計中,cache money在典型狀況下是緩存了100%的查詢,對於這種新冒出來的查詢,要怎麼緩存?
仔細研究的話,這種緩存實際上是能夠作的;但查詢類型增長了,緩存類型增長了,相應的緩存更新策略複雜度也會增長。
這裏的實際問題是:在框架中增長這些複雜度/編碼量,緩存佔用,數據庫的索引空間;而換來的查詢優化是否值得?
這其實不可一律而論,是要視業務場景而定。
若是,以用戶名得到密碼的查詢在產品業務中的調用異常頻繁,甚至就是業務自己100%的調用,那麼神馬編碼複雜度,緩存佔用,索引空間都是浮雲,這是必須付出的代價。
OK,咱們決定作不惜一切代價來實現這個優化;這其實又引入了另外一個問題:
MoSonic支持的查詢類型是不是優化此業務的惟一選擇?
可不能夠在不改變MoSonic現有結構的狀況下來實現這樣的優化?
這個碰巧是有現成的案例,人人網,爲了高效的檢查一個用戶賬號是否有效,專門搞了一整臺服務器作中間層緩存全部×××是否被ban的數據,並提供高效的網絡接口供系統其餘模塊調用。
具體可查閱人人網中間層:實踐篇。
因此,答案是能夠。
MoSonic自己是做爲一個通用的底層ORM框架,它的分佈式支持,緩存支持,都是透明的;但也不強制開發者必須使用;對Cache Money不符合的業務場景,那麼是能夠把緩存禁用掉;開發者根據本身業務特性去尋求更貼切的緩存方案。
設計一個通用的數據庫訪問方案,實質上並不該該對特定業務作特定場景下的優化,而應該留出來空間,讓開發者在遇到特殊場景時有實現特定優化的可能。
若是說,MoSonic把cache money這層透明緩存作成強制的,開發者連禁用某個表的緩存控制都沒有,那纔是設計的問題。
上述,實際上僅討論了一個小細節在單機場景下的狀況,同一個問題若是延伸至分佈式的場景,也會引起不少頗有意思的話題,這篇就先不累述了。