快取(cache)是電腦技術裡的重要概念,從電腦的硬體到軟體架構,無處不充滿著快取的設計。CPU裡頭有快取,用來提供對RAM的快速存取。作業系統裡頭也有快取的設計,用來提供對磁碟I/O動作的快速存取。而一般的應用程式中,也是廣泛運用快取的概念,以提升應用程式執行時的效率。

大家想必都明白快取的基本觀念。一般來說,快取是一塊相對快的記憶體,那麼自然背後會對應一塊相對慢的記憶體。例如,對CPU的快取而言,背後較慢的次級記憶體就是RAM,而對作業系統的磁碟快取而言,背後較慢的次級記憶體就是磁碟了。因此,同樣是RAM,有時候需要其他類型更快的記憶體來做為快取,但有時,也能做為次級記憶體(例如磁碟)的快取,一切端視相對的速度及應用情境下的成本。

就快取的本質而言,快取本身是單位儲存空間成本相對高昂,但存取速度較快的記憶體空間。因此,我們會將次級記憶體中最常被用到的少數資料儲存在快取中,這麼一來,便可以加快這些資料的存取速度,因為毋需至次級記憶體中存取,只需至快取記憶體中,便可讀取這些資料。在有快取存在的情況下,想讀取的資料若在快取中便可取得,稱為命中(hit),反之則稱為誤失(miss)。平均的命中率便稱為hit rate。想當然爾,命中率愈高,代表使用快取的效率愈好。

在使用快取時,基本上可以把快取當做是一個以key對映至value的結構,所有的資料都是以一個key去做對映,以取得資料本身(也就是value)。

快取的基本概念,想必是許多人都十分熟悉,但是運用快取,有不少議題值得討論。而本回就讓我們做一些基礎的探討吧。

快取要有目標,才能得其法
快取這個概念十分具有威力,它不只適用於硬體、作業系統,甚至連一般的應用程式,其實都可以透過運用快取,來得到效率提升的效果。而本文的主題,便是一般的應用程式,尤其是需要存取大量資料庫中資料的應用程式,在使用快取時的各種議題。

雖然運用快取有可能可以提升系統存取資料的效能,但也不是盲目使用就一定可以提升效能。運用的方式最終還是影響到效能提升的幅度,倘若運用的不得其法,有時反而還會拖慢整體的效能。

當你想要運用快取來提升資料存取的效能時,首先,你應該做的功課,便是思考資料的特性,而其中的第一課,便是什麼資料是值得快取的。

因為快取的儲存空間小於次級記憶體,而成本也較為高昂,所以,你不會把所有次級記憶體中的資料內容,全部都丟到快取中,所以必須有所取捨,只有那些最值得快取的資料,你才會丟到快取記憶體中。那麼在有限的資源下,什麼值得快取呢?

要花很多資源取得的資料,優先考量
你首先要考慮的是取得代價高的資料。取得代價高是一個抽象的概念,它可能有不同的意思。如果取得資料的代價,只是單純從次級記憶體取得,那麼不同的資料間可能其代價差不多,差異僅在資料量大小罷了。不過,有些時候,「次級記憶體」不單只是記憶體這種被動的角色,事實上,它有可能具備計算的主動能力,最常見到的例子,就是資料庫了。

在現在,對資料庫中資料的存取,快取的運用已經相當普遍了,而資料庫就不是一種單純的「次級記憶體」。當你透過SQL述句存取資料庫時,資料庫伺服器都必須進行某種程度的運算,尤其當你的SQL述句愈複雜時,資料庫伺服器所進行的運算通常也愈複雜,這使得存取不同類型的資料所需的代價,會有明顯的不同。你可以想像,在資料庫伺服器上取得速度愈慢的資料,愈是值得放到快取中來提升它的存取效率,因為它一旦可以在快取中取得,便毋需花費大量的時間至資料庫伺服器中存取,效率自然會大幅提升。

依資料受到存取的頻率來選擇
但是,也並不是所有存取速度慢的資料都應該丟到快取中去提升其存取的效率,接下來你還必須考慮第二個因素,也就是這個資料被存取的頻率。一個很少被存取到的資料,即使把它放到快取中,單看這筆資料的存取效率可以得到很大的改善,但因為其存取頻率低,所以即使是改善它,終究對於整體的效能不會有太大的影響。但是,一個存取頻率高的資料,其存取的速度便足以支配系統整體效能的一大部份,那麼,透過快取來提升其存取速度,對系統整體效能的改善,自然顯著多了。

所有的效能調校都是一樣的道理,打蛇要打七寸,調校效能要從支配比例大的部份來著手。

因為快取資源既有限又昂貴,所以你一定要先分析資料存取的特性,才會知道究竟應該要把那些資料放到快取中。當然,那些存取速度較慢、又時常會被存取到的資料,肯定是優先考慮要放置到快取中的部份。

資料更新的週期太短的環境較不適合
再來,你必須思考資料的更新週期。通常,很少有資料一直會保持恆久不動的,所以資料都會變動,只是變動的週期不盡相同罷了。而當資料被放到快取中,但又發生變動時,會有幾種不同的策略可以因應。

有些應用下,你可以允許快取中資料和資料庫中資料不一致,因為這不會造成太大的影響。但是,在更多的應用中,你會希望它們是一致的,這個時候,你就會需要從資料庫中重新載入新的資料至快取中。

當資料更新的週期很短,你會發現,其實資料還是必須反覆不斷從資料庫中取出,而且還多出了額外的動作,也就是放置到快取中的動作。這麼一來,可能無法從快取機制得到好處,反而付出了因為快取而額外衍生出來的代價。換句話說,當資料更新週期愈長時,愈能夠從快取的機制中得到好處,因為不會在很短的時間內反覆不斷從資料庫中取得資料放到快取中,而這資料或許根本還沒有使用到,就又被重新載入了。

置入的資料量要有所節制
最後一個要考慮的特性,那就是資料量了。通常,快取記憶體的空間都有限,我們不會無限制把所有東西都往裡頭丟,資料量太大的資料,放到快取記憶體的空間之後,等於就排除了某些資料被快取的機會,因此,你必須有所取捨。

當然,目前提到的這四個因素都是可能影響到是否將資料置於快取中的因素,你必須整體來衡量,無法由單一個因素來決定。

例如,一個存取速度極慢、但是存取頻率極高、更新週期極長的資料,你便有可能因為它影響系統效能的比例甚巨,即使它的資料量頗大,還是決定把它放到快取中。相反的,一個存取頻率低的資料,即使資料量再怎麼小,把它丟到快取去,也是沒有任何意義。

所以,設計者終究還是必須權衡各個因子,挑選出適合放到快取中的資料。挑選正確的資料,快取能為你系統帶來的效能提升就大,反之,不僅可能無法提升效能,可能還會拖慢。由此可見,分析你資料的特性再做正確的決策,對於運用快取究竟有多重要了。

作者簡介


Advertisement

更多 iThome相關內容