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