Sheets 當資料庫的資料模型設計,核心原則是「一列一事件、欄位固定、只 append 不改」。這種形狀叫 raw log(原始紀錄):每筆瀏覽就是一列、寫進去就不再動它,彙總與分析交給後續的排程另外算。先講為什麼這樣設計,再講這張表能長到多大。

raw log 的欄位設計

raw log 表每一欄對應一個固定的維度,每一列是一筆完整的事件。流量統計的 raw log 大致是:

時間路徑來源語言裝置
2026-07-06 20:11:03/posts/foo/google.comzh-TWmobile
2026-07-06 20:11:47/automation/en-USdesktop

三個設計決定讓這張表好用又好彙總。時間放第一欄、用接收端的伺服器時間,讓資料天然按寫入順序排列,也讓「某天的資料」用時間範圍就能篩。每一欄都是原子維度、不把多個資訊塞進一欄(不要把「路徑+裝置」合併成一欄),因為彙總時要能單獨 group by 路徑、或單獨 group by 裝置,欄位分開才做得到。只 append、不回頭改已寫的列,讓這張表成為不可變的事實紀錄——要改的是彙總結果、不是原始 log,原始資料保持乾淨才能隨時重算。

raw log 直接看沒有意義(幾千列逐筆瀏覽),它的價值是當彙總的原料。把 raw log 依日期與路徑 group 成「每天每篇看幾次」的日報,是模組四:觸發器與排程的工作。

Sheets 的容量邊界

Sheets 是為「人看的試算表」設計的,不是高吞吐資料庫,所以它有兩類上限要放在心上。

總 cell 數上限:單一試算表有一個總儲存格數量的硬上限(目前以千萬 cell 計,Google 會不定期調整,實際數字以官方為準)。raw log 每列的 cell 數等於欄數,5 欄的話,這個上限換算成列數是相當大的量——對個人 blog 是好幾年的資料,不會很快碰到。但它是有限的,不是無限成長。

讀寫效能隨列數下降:實務上先浮現的邊界是效能,比硬上限更早遇到。當 raw log 累積到數萬、數十萬列,任何「整表讀進來算」的操作(例如彙總 trigger 每次全表掃描)會越來越慢,可能逼近觸發器的單次 6 分鐘執行上限

撐不住的訊號與應對

判斷 Sheets 開始撐不住,看這幾個訊號:彙總 trigger 的執行時間逐月變長、逼近 6 分鐘;開啟試算表本身變慢、捲動卡頓;或 cell 數逼近上限的警告。出現這些訊號時,有兩條應對路徑,依情況選:

分表:把 raw log 按月(或按季)拆成多張工作表,例如 log-2026-07log-2026-08。彙總 trigger 只讀當月表、不必掃全部歷史,執行時間就回到穩定。這是最小改動、繼續留在 Sheets 的做法,適合量成長但還在 Sheets 能力範圍內。

遷移:當量大到連分表都吃力、或需要更即時的查詢,訊號就指向「該換更重的儲存」——把接收端從 Apps Script 換成 Cloudflare Workers + D1(免費 SQLite),資料庫的查詢能力與吞吐遠高於 Sheets。遷移的完整訊號與路徑在模組五,選型的取捨在模組零

判準用一句話收斂:Sheets 撐不住的第一訊號通常是彙總變慢、不是 cell 爆掉——先分表爭取空間,分表也吃力才談遷移。對絕大多數個人 blog,這些邊界很久才會碰到,先讓簡單版跑著、留意訊號即可。

事件模型會改變這裡的估算

上面的估算假設一次瀏覽產生一列。模組六的事件模型把它改成一進一離兩列,並在 payload 上多加六個欄位——列數接近翻倍、單列的 cell 數從五增為十一,兩者相乘之後容量上限會比這裡算出來的早很多抵達。真要估的話,用那一章的欄位清單重算一次,而不是沿用這一節的數字。

下一步

資料進來、也知道表能長多大之後,把 raw log 變成看得懂的日報,見模組四:觸發器與排程