(轉)面向Web 2.0的儲存引擎設想:充分利用資料訪問扭曲

denniswwh發表於2009-07-23

原文作者:風輕揚

出處:http://wangyuanzju.blog.163.com/blog/static/1302920070245344752/

警告
此為冗長的純技術帖,為我對於Web 2.0的儲存引擎如何充分利用資料訪問扭曲這一特點來提高效能的一些想法。對於不關注細節的使用者可以只看以下幾個要點:

  1. Web(2.0)應用的資料訪問模式通常具體扭曲性,即少量資料被頻繁訪問,其餘大量資料很少被訪問
  2. 傳統的資料庫採用的頁級快取可以利用資料訪問本地性,但對資料訪問扭曲性通常與事無補
  3. 利用資料訪問扭曲的第一招是使用記錄快取,其效果是使相同的記憶體能夠快取更多的頻繁訪問的記錄
  4. 利用資料訪問扭曲的第二招是高頻記錄聚簇,即將頻繁訪問的記錄從物理上聚簇在一起,其效果是使相同的IO操作可以讀入更多的頻繁訪問的記錄
  5. 記錄快取已經在一些產品中使用,但應用不多還不清楚實際效果如何,高頻記錄聚簇是我瞎想的,並未在知名資料庫產品中使用
[@more@]

正文開始

在上一篇介紹Falcon體系架構的文章中 我們可以看到在資料庫業界有著20年實踐經驗的Jim Starkey在其(號稱)面向Web尤其是Web 2.0應用而設計的MySQL新型事務型儲存引擎Falcon時,採取了記錄快取為主、頁面快取為輔的架構。在我看來,這一架構能夠充分發揮作用的前提是 資料訪問要具有扭曲性,同時資料訪問扭曲也是大部分Web 2.0應用的特點,但我認為這一架構只是儲存引擎面向Web 2.0中資料訪問扭曲這一特點進行最佳化而走出的第一步,還可以走得更遠,獲取更好的效果。

首先回顧一下傳統資料庫所採用的頁面快取機制。 由於對資料庫早期的發展歷史缺乏研究,我不清楚當初為什麼這一快取機制會獲得流行,不過據我看來至少有以下三方面的原因:1)軟體與磁碟資料互動的單位天 然的是適合以塊為單位進行的,因為讀取一個塊所用的時間也讀取塊中一個位元組所用的時間幾乎沒什麼差別;2)按頁面為單位組織資料易於實現;3)資料訪問本 地性的影響。

這其中起決定作用的可能是資料訪問的本地性。本地性可以是每個計算機系的學生都清楚不過的一件事,也確實存在於大部分程式的資料訪問模式中,包括對資料庫中資料的訪問。由於本地性的影響,以頁為單位快取資料絕對是有益的,因為最近訪問的記錄附近的記錄也很可能會被訪問到。

然 而,對於Web(2.0)應用而言,資料訪問的扭曲性可能會比資料訪問的本地性更為顯著,至少是同樣顯著。所謂資料訪問扭曲性是指同等型別的各個記錄被訪 問的頻率與均勻機率相比相去甚遠。如Blog應用中一般只有少量熱門Blogger的文章(如新浪部落格的老徐)被頻繁訪問,其它使用者的訪問則很少會被訪問 不,另一個例子是對所有使用者來說,一般新文章和少量熱門訪問被訪問的機率都遠大於其餘文章。

有時可以透過一些資料組織手段來實現特定的數 據本地性,從而利用資料訪問扭曲性帶來的好處。如對於上述的第一個例子,可以使用索引組織表技術,按使用者聚焦文章內容。但這一方法會帶來其它的問題,如發 表文章時的插入點很分散,從而導致B+樹的隨機訪問的過多的分裂。在有些情況下,資料訪問扭曲性和資料本地性之間是不可轉化的,如對於上述一個使用者中的某 篇訪問被頻繁訪問的情況(修改應用,將經常會被訪問的文章複製一份放到一個較小的表中可能是一個方法)。

現在再來說Falcon中的記錄 快取,記錄快取的作用在於可以將所有的記憶體都用來儲存那些真正會被訪問到的記錄。當頻繁訪問的記錄能夠完全或基本上被快取在記憶體中時,這一方案是完美的。 但若頻繁訪問的記錄過多,即使使用了記錄快取機制也遠遠不夠快取所有這些記錄時,記錄快取機制並不能有效的降低系統IO。記錄快取提高的記憶體的利用率,相 對於頁面快取可能可以將快取失配率從80%下降到70%,但對IO來說只相當於下降了1/8。

解決這一問題的手段,我個人認為一個比較有 效的是對資料進行持續不斷的動態重組,將頻繁訪問的記錄聚簇到一起,暫時稱之為高頻記錄聚簇吧。這一手段的有效性可以透過與記錄快取的對比體現,記錄快取 的作用是使同樣的記憶體可以用來快取更多的頻繁訪問的記錄,而高頻記錄聚簇的作用將是使同樣的IO操作可以用來讀入更多的頻繁訪問的記錄,從而實現減少系統 IO(主要是讀IO)的目的。

實現高頻記錄聚簇的主要困難在於需要移動記錄的儲存位置。在傳統的資料庫實現中,記錄的位置由物理 rowid表示,物理rowid的一般構成為記錄所在頁號和頁內的槽號,索引中需要記錄rowid並據此來找到記錄。若在跨頁面移動記錄,則要修改所有索 引中的rowid,是一個代價相當大的的操作,因此在實際的資料庫中,除了一些人工命令對記錄進行重組外,都不會跨頁面移動記錄。而且重組的程式碼非常大, 重組過程中表一般幾乎不可用。

要實現自由的跨頁移動記錄,就必須實現邏輯rowid。將邏輯rowid對映到物理rowid的操作要求要 儘可能高效的完成,因此基本上需要將這一對映表完全快取中記憶體中。這在很長一段時間裡是不現實的,但在記憶體容量日益增加的今天,這一方法日益值得一試,即 使是使用最最簡單的陣列對映法。有一些簡單的方法就可以大幅度減小這一對映表的大小,比如說將資料組織成頁組,記錄只在組內移動就可以減少對映表的大小。 如每條記錄一個位元組就可以將記錄儲存位置對映到包含256頁的頁組內的任意一個頁,則進行組內重組,在頻繁訪問的記錄佔1/256或以上時就可以實現很好 的聚簇效果。

據我的經驗,很多Web應用中的記錄大小都會有200個位元組左右,這樣“邏輯rowid->物理rowid”對映表佔 用的空間大概是資料量的1%。對於一臺4G記憶體的伺服器,若使用500M作為儲存對映表即可以處理100G的資料。對於操作頻繁的Web應用資料庫來說已 經是相當令人滿意的了。當然,對於某些記錄比較短的表這一技術並不適用。

總之,對於資料訪問扭曲普遍的Web(2.0)應用,記錄快取技 術和高頻記錄聚簇技術我個人認為有望成為提高儲存引擎效能的有效手段。前一個技術已經在Falcon中實現了(一些Java實現的DBMS中也有采用這一 技術的,但應用不廣),效果我們即將看到,後一個技術是我胡亂想的,不知道有沒人真的在做這方面的工作?

關於高頻記錄聚簇的實現方法,使 用邏輯rowid和自動重組只是其中一種方式。其它的方法應該還是很多的,對於可用性要求不太高的應用,定期使用外部程式進行人為的聚簇重組,更新所有索 引也不是不可行。但不管用什麼方式實現,將訪問頻率高的記錄聚簇在一起我想會是充分利用資料訪問扭曲來提高資料庫效能的必要條件。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/124805/viewspace-1024487/,如需轉載,請註明出處,否則將追究法律責任。

相關文章