Re: [討論] 存取即時資料用檔案 or 資料庫,哪個好?

作者: GALINE (天真可愛CQD)   2021-03-21 16:26:13
不知道過了一個月還來不來得及幫上原 po...
若想法是「DB 好肥,不想裝」,建議可以研究一下 sqlite
這個「資料庫」就只是一個檔案而已,不用另外跑一套系統起來
Unix 系(Linux/Mac/BSD...)的作業系統裝 PHP 通常預設包含 sqlite
用 Windows 可能要研究一下,像 xampp 就要另外處理
( https://stackoverflow.com/questions/61086512 )
程式範例
// database.sq3 是你的 DB 檔案,不存在的話會自動被建立
// 另,這年頭建議盡量用 PDO,必要的時候才用 mysqli 之類針對特定 DB 設計的介面
$pdo = new PDO("sqlite:/path/to/database.sq3");
// 跑兩句 SQL,一句開 table,一句寫資料進 table
// 因為是範例所以簡單寫,線上程式務必用 prepared statement,不然會碰到 https://xkcd.tw/327
$pdo->exec("CREATE TABLE test_table (id INTEGER PRIMARY KEY AUTOINCREMENT, value TEXT)");
$pdo->exec("INSERT INTO test_table (name) VALUES ('The string')");
速度跟直接讀寫檔案差不多,但是能變的花樣多很多,資料被寫壞掉的機會低很多
: 比起檔案存取,感覺用像是mysqli之類的函數頻繁地存取這些小而簡易的狀態值有如「用大砲打小鳥」
: 似乎沒什麼必要,而且感覺效能也不會有所變好(甚至可能變得更差也說不定… )
效能不是感覺出來的,是測出來的...
可以參考別人的 benchmark 當成想像的起點
不過大家用要面對的問題或機器大小(a.k.a 口袋深度)都不一樣
可以試看看自己寫效能測試,然後思考效能測試跟現實環境可能有哪些差距,然後再來評估
例如說這裡簡單寫了一個 sqlite 跟直接寫檔案的比較
https://gist.github.com/CQD/745793eea05e86925a646184ac6f70db
但這個比較也不一定會符合你的程式的實際效能
例如說,修改上面的測試,不在迴圈裡面 new PDO 而是重複使用 $pdo 的話,寫入/讀取的速度會變成十倍快
然後我的電腦跟你的機器測出來的速度也很可能不一樣
什麼是大砲什麼是小鳥要看你實際系統規格,以及需要面對的流量壓力,以及你想花多少錢
即時讀寫檔案沒碰到問題的話,表示你要處理的流量壓力就不大,適合走的路跟大流量就會不一樣
: 所以各位對於「存取這種小量簡單但可能會有多人同時存取相同即時狀態值應該用什麼方式存取」有什麼看法?
: 除了用File、Database外,還有其他更好的存取方式嗎?
「很多人同時讀寫」會讓「資料一致」很難做,處理這件事情的基礎就是上 OS 的時候會講到的 locking
https://ntust-csie-islab.github.io/106-OS-homework1/B10415021/
自己讀寫檔案就是自己要面對這種問題
如果讀寫量很少,或是存取速度超級快,出事的機會很低
如果存取量很大,或硬碟有點不太行卻又沒死透,這題就會變成寫很難寫的 OS 作業(寫對還沒分數)
而且最討厭的不是那種每次都壞掉的,而是那種在線上戳很多次才會壞掉一次的,自己手戳很難重現
(例如三十個人同時看我的上線狀態,其中 29 個人看到上線,一個人看到離線)
(或偶而就是有人的上線狀態被其他人的上線狀態蓋掉)
那些敢自稱資料庫的東西通常在相關的事情上面下了不少苦功
https://zh.wikipedia.org/zh-tw/ACID
所以用資料庫的話,雖然效能不一定能保障,但是資料不會爛掉這件事情是遠比自己寫檔案有保障的
處理效能問題通常是以下三種方向
- 把資料放在讀寫很快的地方
- 把工作打散到多個硬體裝置上
- 資料結構,演算法,或論文裡面寫的神秘數學公式
第一點的意義是:如果能用 SSD 就往 SSD 丟,如果能寫進記憶體就寫進記憶體
如果現在的架構已經開始碰到資料一致性的問題,然後你口袋又有錢可以花在這上面
那買顆 SSD 來存資料就滿有可能讓問題緩解甚至消失,不一定需要改 code
或者可以考慮在機器上架個 memcache 然後資料都往裡面寫,SSD 快不過記憶體。
不過記憶體裡面的東西只要重開就沒了,能否接受要看你的功能規格而定。
如果你真的很有錢,可以考慮 Intel 的 Optane,跟記憶體差不多快的硬碟,根本黑魔法
若走進這條路請務必與版友分享使用心得...
另外也有一些東西是一開始就預設把資料存在記憶體裡面
例如上面提到的 memcache,或這幾年興起的 redis
不過靠單台機器的硬體效能提升來解終究有極限
會不會踩到極限就看這個生意(?)做得多好
如果你的資料太多,沒辦法全部塞進比較快的硬碟/記憶體裡面,只能塞一部分進去
那這種招數就叫 cache。然後就要開始考慮 cache 跟主資料怎麼同步,cache 什麼時候過期...
功能比較完整的資料庫也會做類似的事情,例如 MySQL 就會把常用資料放到記憶體裡面。
所以大的資料庫在推上服務之前會先「熱機」,用 query 讓機器把常用資料先載入好
照我們家 DBA 的說法,有沒有熱過效能差滿多的...
當然也可以把 MySQL 的資料庫開在 SSD 甚至 Optane 上面。
第二點大部分人應該不會想自己寫程式處理
實務上的例子有 DB 的 cluster 或讀寫分離機制
另外 no-sql DB 也有不少是為了這點做努力
Hadoop 也是在幫你做這件事
光是確保「不同裝置上讀到的資料一致」就是一屁股痛
第三點大部分人應該還是不會想自己寫程式處理
不過有個值得一提的例子,有些資料庫的 index 實作概念上就是個 B+ tree
想要自己土炮的話,這應該是 OS 作業加分題等級能做的出來的東西
我個人是不會拿 PHP 來做這種事情就是了
: 我目前全是用像file_get_contents、file_exists、file_put_contents、fopen等類的函數來操作使用者即時狀態值的檔案
: 要全改成另一種方式,光改寫程式大概就是個大工程了吧…
你現在知道什麼叫做 legacy code 跟 refactor
也知道為什麼會有人說「東西沒壞就不想修」了
作者: shvanta (vant)   2021-03-21 22:56:00
每次看G大的文都有如醍醐灌頂,真的不推不行
作者: bakedgrass (蒙古烤小草)   2021-03-22 02:07:00
作者: freeman371 (自由人371)   2021-03-26 10:30:00
推,謝謝你!

Links booklink

Contact Us: admin [ a t ] ucptt.com