漂J
@floatj
好奇
Tue, Jul 6, 2021 1:16 PM
1
遇到一個簡單的(?)MySQL 問題,到底應該 INSERT 還是 UPDATE,對資料庫效能的衝擊才能降到最低啊
漂J
@floatj
Tue, Jul 6, 2021 1:17 PM
假設有個機器人,使用者可以跟機器人對話,每次對話的時候對話的使用者的 ID 跟時間都會被記錄到資料庫。
每天會從資料庫撈出 24 小時內有跟機器人對話過至少一次的使用者的清單 (每天只會撈一次)
漂J
@floatj
Tue, Jul 6, 2021 1:18 PM
這樣到底該每次使用者對話都 INSERT 一次,還是 UPDATE 最後對話的時間就好
Tsuki-勝ったな、ガハハ!
@LegoMania
Tue, Jul 6, 2021 1:24 PM
insert on duplicate key update
Tsuki-勝ったな、ガハハ!
@LegoMania
Tue, Jul 6, 2021 1:25 PM
我不清楚該table是否有其他query需求
達人🐉☄️💫
@c910335
Tue, Jul 6, 2021 1:26 PM
我選後者
漂J
@floatj
Tue, Jul 6, 2021 1:27 PM
Tsuki-勝ったな、ガハハ!
: 現在的確是用 insert on duplicate key update 沒錯,表應該算滿常被 query 的,但 update 的頻率應該相對比較低
Tsuki-勝ったな、ガハハ!
@LegoMania
Tue, Jul 6, 2021 1:28 PM
所以主要的負擔是Read,不是Write?
漂J
@floatj
Tue, Jul 6, 2021 1:33 PM
這倒是好問題,沒有認真研究過
漂J
@floatj
Tue, Jul 6, 2021 1:33 PM
應該 read 多一些, write 應該只集中在特定時段
Tsuki-勝ったな、ガハハ!
@LegoMania
Tue, Jul 6, 2021 1:39 PM
Tue, Jul 6, 2021 1:40 PM
這樣的效能最佳化有點玄
漂J
@floatj
Tue, Jul 6, 2021 1:40 PM
一張 table 塞了三種類型的 record
感覺省了 schema 卻拖累效能
漂J
@floatj
Tue, Jul 6, 2021 1:41 PM
算了還是別想太多,繼續用 insert on duplicate key update 應該即可?
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:46 PM
「到底應該 INSERT 還是 UPDATE,對資料庫效能的衝擊才能降到最低」
如果問題是這個的話,我建議 always insert,印象中 b-tree 在 insert 的時候最多只要預先分配空間,update 的話好像要重建
漂J
@floatj
Tue, Jul 6, 2021 1:47 PM
日 落
: 我也印象中某些論點是這樣說,但多方查詢資料後,好像也不是總是如此
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:48 PM
Top 84 MySQL Performance Tips | Debian Admin
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:49 PM
mysql insert vs update performance
漂J
@floatj
Tue, Jul 6, 2021 1:51 PM
感覺我沒定義清楚,如果要 INSERT 應該就要開另外一張 table,然後只做 INSERT
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:51 PM
Is mysql UPDATE faster than INSERT INTO?
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:52 PM
MySQL: Is it faster to use inserts and updates inste...
日 落
@zeroplex
說
Tue, Jul 6, 2021 1:55 PM
我不是很清楚你目前的問題和運作環境,除非差異很大,不然我會先考慮維護成本,效能問題花錢解決快很多
漂J
@floatj
Tue, Jul 6, 2021 1:57 PM
維護成本的話,我感覺好像還是 UPDATE 的版本好些
畢竟 code 都寫好了,只是突然有點越想越不對勁
這樣也不用再多開一張 table,只要修改原本 table schema 就好
日 落
@zeroplex
說
Tue, Jul 6, 2021 2:07 PM
我想確認一下,目前在討論的是「對話記錄」的 table?還是「使用者統計」的 table?
Mr. Push
@ue19882000
說
Tue, Jul 6, 2021 2:08 PM
如果你那張表的欄位寬度沒到很寬,我會覺得 update 比較好,InnoDB 本身有對 page 做 cache,如果是短時間互動頻率高的話這些熱頁會一直躺在記憶體力,把耗時的 I/O 壓到最低,但如果是一直 Insert 的話,會產生很多的 I/O,如果互動頻率高到來不及 I/O 的話你的整個 DB 會卡住,不過我覺得對話記錄 9 成 99 會再拿來做其它分析啦... 先存起來不見得是壞事 =w=
漂J
@floatj
Tue, Jul 6, 2021 2:08 PM
日 落
: 主要是作對話紀錄跟使用者的狀態紀錄沒錯
其實一張表有好幾個用途
,統計的部分基本上是一天作一次
漂J
@floatj
Tue, Jul 6, 2021 2:09 PM
咦不對我在講什麼 = = 這樣跟上面的講的讀多寫少好像又不一樣了
日 落
@zeroplex
說
Tue, Jul 6, 2021 2:09 PM
漂J
: 你該睡了
Tsuki-勝ったな、ガハハ!
@LegoMania
Tue, Jul 6, 2021 2:10 PM
他這時間正要開始工作
漂J
@floatj
Tue, Jul 6, 2021 2:11 PM
Mr. Push
:
把對話紀錄存起來的確有考慮到事後可以再拿來分析的可能,雖然我覺得真正用到的機會不大。Insert 的 I/O 會產生比較多這個我倒是沒想到...
漂J
@floatj
Tue, Jul 6, 2021 2:12 PM
仔細想想,這張表果然還是寫入的頻率比較高,讀取應該還是略少於寫入
漂J
@floatj
Tue, Jul 6, 2021 2:13 PM
自作聰明把 schema 擴充想節省 table 結果搞到表的用途越來越複雜的下場
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 4:42 PM
你這種就是標準的寫 log 啊
這種時候應該是考慮換 DB 而不是繼續用 MySQL
btw, 我選 update,因爲 insert 是 table lock,update 有機會做到 row lock
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 4:43 PM
對了,你已經遇到效能衝擊而需要開始思考最佳化的問題了嗎? 如果沒有的話,就放置啊
漂J
@floatj
Tue, Jul 6, 2021 4:53 PM
l• ܫ•) Davyキュルッ
: 我有想過其實應該很適合用 Redis,但怕增加以後架構維護的複雜度而作罷
漂J
@floatj
Tue, Jul 6, 2021 4:53 PM
原來 insert 會 table lock
漂J
@floatj
Tue, Jul 6, 2021 4:54 PM
效能衝擊算稍微遇到,之前因為這樣把 Cloud SQL 的硬體配置加大,但是想想也不是長久之計
漂J
@floatj
Tue, Jul 6, 2021 4:56 PM
因為是沒寫入也不會真的影響太大的東西,所以就算 Redis 不幸爛掉又復原不了也不會怎樣,頂多那天不要統計數據 (現在每天手動跑也常常忘記),但就卡在我覺得這樣架構變複雜對未來不知道是不是好事…
漂J
@floatj
Tue, Jul 6, 2021 4:57 PM
但說真的其實變複雜好像也沒差,反正現在本來就有服務依賴 Redis,硬幹多增加另一個會寫入 Redis 的設計好像也不會有人阻止我
漂J
@floatj
Tue, Jul 6, 2021 4:59 PM
反正都有現成的 Redis 了,不用白不用,架構變複雜也不一定是壞事吧
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:12 PM
怎麼會用 redis...
適合存 log 的 db 這麼多
而且你是集中在一個時間統計
直接存到檔案裡面用 awk sed perl 之類的處理都比較快
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:15 PM
innodb 是有想辦法避開這種 lock 但如果你的 id 是 AI 的話還是會需要整張 lock
漂J
@floatj
Tue, Jul 6, 2021 5:16 PM
l• ܫ•) Davyキュルッ
: 因為 Infra 現在就已經有 Redis 啦,不用再多增加第三種 DB 讓架構更複雜
漂J
@floatj
Tue, Jul 6, 2021 5:16 PM
嚴格說起來只是存一個數值而已,核心需求是存跟使用者最新一次對話的時間點,因為本來想說反正都有可能要 INSERT 了,不如把整個對話的內容也一起存起來
漂J
@floatj
Tue, Jul 6, 2021 5:17 PM
user_id | last_update_time 大概就存這兩個欄位是關鍵而已
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:19 PM
我有看懂哇 不用一直重複吧XDD
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:19 PM
是說你這個問題 是不是好幾天前也問過了
漂J
@floatj
Tue, Jul 6, 2021 5:20 PM
l• ܫ•) Davyキュルッ
: 沒吧
難道我穿越了
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:22 PM
有吧 幾個月前
漂J
@floatj
Tue, Jul 6, 2021 5:23 PM
沒印象了,已從短期記憶被 flush 掉
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:28 PM
像是這個啊
@floatj - 自己好像劣質工程師
l• ܫ•) Davyキュルッ
@david50407
Tue, Jul 6, 2021 5:32 PM
或是這個啊
@floatj - 萬事問噗友 在想一個 state machine 的邏輯應該放在哪邊比較好的問題,如...
漂J
@floatj
Tue, Jul 6, 2021 5:39 PM
喔喔原來是這兩則噗啊
得證我會上來發廢噗的都是同一個專案欸
最後都參考噗友的建議行事了
除了 transaction 的沒有辦法完全做到以外
漂J
@floatj
Tue, Jul 6, 2021 5:39 PM
Tue, Jul 6, 2021 5:39 PM
不過問題還是不完全一樣吧,只是都跟 DB 有關
漂J
@floatj
Tue, Jul 6, 2021 7:43 PM
Want to use Redis as an events statistics store
發現用 Redis 來處理好像也頗不好使
漂J
@floatj
Tue, Jul 6, 2021 7:48 PM
而且如果用 ZADD 還有要排程刪除過期資料的問題
載入新的回覆
每天會從資料庫撈出 24 小時內有跟機器人對話過至少一次的使用者的清單 (每天只會撈一次)
感覺省了 schema 卻拖累效能如果問題是這個的話,我建議 always insert,印象中 b-tree 在 insert 的時候最多只要預先分配空間,update 的話好像要重建
畢竟 code 都寫好了,只是突然有點越想越不對勁這樣也不用再多開一張 table,只要修改原本 table schema 就好
其實一張表有好幾個用途,統計的部分基本上是一天作一次他這時間正要開始工作自作聰明把 schema 擴充想節省 table 結果搞到表的用途越來越複雜的下場這種時候應該是考慮換 DB 而不是繼續用 MySQL
btw, 我選 update,因爲 insert 是 table lock,update 有機會做到 row lock
但說真的其實變複雜好像也沒差,反正現在本來就有服務依賴 Redis,硬幹多增加另一個會寫入 Redis 的設計好像也不會有人阻止我適合存 log 的 db 這麼多
而且你是集中在一個時間統計
直接存到檔案裡面用 awk sed perl 之類的處理都比較快
難道我穿越了得證我會上來發廢噗的都是同一個專案欸最後都參考噗友的建議行事了
除了 transaction 的沒有辦法完全做到以外