用一句簡單的話說
Approximation Pattern 透過儲存不是必要精確的資料來幫助我們減少 db 資源的損耗
場景
在一些資料數量龐大的場景下資料更新的頻率會很高,當精確的統計數字並不是必須的情況下,可以透過計算大概正確的值來減少資料更新的頻率,場景可以是人口統計、企業數量等等,邏輯通常實作在 application code 裡
以下是 MongoDB official course 以及 documentation 的兩個範例
範例一:
在一個 e-commerce App 中需要顯示每個產品的平均 rating,因為該產品的 rating 會頻繁更新而且數量龐大容易拖慢速度,為了改善效能,我們犧牲掉一點評分的準確度,在 App logic 加上一個 random number generator 可以隨機產生 1~10 的數字,當數字是 10 時才進行 write 複寫平均 rating
此時我們將 rating count + 10 以及將新的 rating 分數乘以 10 來更新 rating 資料
{ product_id: 1000, name: 'a good product', rating: { rating_count: 89200, avg_rating: 4.9 }, price: 300, store: 'online' }
{ product_id: 1000, name: 'a good product', rating: { rating_count: 89200 + 10, avg_rating: (4.9 * 89200 + 5 * 10) / (89200 + 10) }, price: 300, store: 'online' }
|
結果就是減少了 90% 的寫入頻率,並增加了效能
範例二:
在一個城市人口統計的 App 中,我們在每次人口發生變化時都會新增一個 document
db.population.insertOne({ city: "New Perth", population: 40000, date: ISODate("2022-09-15") })
|
但因為人口數量頻繁變化而我們通常又不需要非常精確的人口數字,於是我們決定在人口變化量大於等於 100 的時候才紀錄當下的人口數
let population = 40000 function updateStoredPopulation(curr_population, new_population) { let population_change = Math.abs(curr_population - new_population) if (population_change >= 100) { db.population.insertOne( { city: "New Perth", population: new_population, date: Date() } ) population = new_population } }
[ { city: "New Perth", population: 40100, date: ISODate("2024-09-20") }, { city: "New Perth", population: 40200, date: ISODate("2024-10-01") }, { city: "New Perth", population: 40300, date: ISODate("2024-10-09") }, ]
|
透過上述的兩個例子可以發現,Approximation Pattern 實做方式可能是多變的,但最終的目標都是透過計算約略正確的值來減少資源的消耗。
影片說明 (en)