看板 Soft_Job 關於我們 聯絡資訊
想請教一下,讀取一頁的時候 db 的query 次數會是一個重要的考量嗎? 效能、維護性、安全性等等 db server跟app server是不同主機,每個query也不複雜 假設有2個做法 A. 透過3-4個query,table 拉回來的資料就是可以直接用的 B. 把多個table join成一個query,一次把資料拉回來 然後程式邏輯需要在處理一下,這個程式邏輯也不複雜 A跟B哪個做法比較好,會有差異嗎? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 223.137.234.97 ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1537159174.A.125.html
shvanta: 個人認為B的做法較好,一方面減少HTTP Request數,一方面DB 09/17 12:48
shvanta: 對常用SQL,其實是有自己的機制讓運行加快 09/17 12:49
gmoz: 次數跟資料量之間的平衡 09/17 12:59
alan3100: 會問這問題就選A. 你分不清楚A和B差異,選B對後人80%賽康 09/17 13:11
oopFoo: 要B的話,就直接改用redis。以前是用memcached 09/17 13:11
asleepme: 請教alan大,其中的差異跟B造成康的原因是什麼?感謝~ 09/17 14:32
BignoZe: A 對 db 效能較好,B 可做的事情較多。 複雜的需求B,簡 09/17 14:46
BignoZe: 單的需求 A,試著用 explain 指令看看 db 實際搜尋的方法 09/17 14:46
BignoZe: 和搜尋的資料筆數來判斷。這邊是如果資料量大才需要考慮 09/17 14:47
BignoZe: 如果資料量小,過早的最佳化是一個反模式 09/17 14:48
skitty: 可能出來ABCD 半年後說C資料有錯 後人要連ABD一起看 09/17 14:49
BignoZe: 較複雜的話可以寫測試 很容易寫的 要錯也難 09/17 14:54
謝謝大家的建議~ 那延伸一下我的問題好啦,其實主要也是我query寫的不好 T_T 我的狀況如下,就是有2個table X, Y,要把Y做某種運算後跟X join在一起 table部分內容示意圖如下 table X user_id| object_id| attr_a| attr_b 1| 1| a| b (user_id, object_id) 不重複 table Y Y_id| user_id| object_id| content_c | content_d 1| 1| 1| c-1 | d-1 2| 1| 1| c-2 | d-2 3| 1| 1| NULL | d-3 要做的事情就是已知 user_id, 從X找出這個user_id的所有rows 對Y做的則是對同一個 user_id 找出 SELECT COUNT(content_c) / COUNT(content_d) as content_ratio , object_id as object_id FROM `Y` WHERE user_id = '1' group by object_id 然後2個join起來,但是要把那個count divide的結果join起來 一直遇到困難,這種要怎麼join呢? ※ 編輯: asleepme (223.137.234.97), 09/17/2018 15:09:56
testPtt: declare 去拆分需要的 少用多重join 09/17 15:02
BignoZe: table設計怪怪的 table A user_id, object_id 是 uniq 09/17 19:36
BignoZe: 那 table Y 可以直接關聯 foriegn key x_id 09/17 19:37
BignoZe: 這邊統計要回歸你的需求 你要統計的是什麼值 感覺上是可 09/17 19:38
BignoZe: 先 join 再用 group 和 count 做運算 09/17 19:38
BignoZe: 統計的話就不用管效能了 怎麼弄都是 slow query 09/17 19:39
TAKADO: 通常是B,但沒有標準答案吧,要看應用場景。B沒寫好很容易 09/17 20:55
TAKADO: 讓DB炸掉,尤其當join其中一張是上百萬千萬筆的資料表。 09/17 20:55
asleepme: 感謝大家對db相關的指導~ 至於應用.. 剛剛改變了 XD 09/17 22:22
alog: 基本上要看你的瓶頸是什麼 再來決定優化手段 09/17 22:36
crossdunk: 看資料量吧 09/17 22:36
alog: 如果那頁是高流量 or 該頁 request 數量1秒內是所有頁面requ 09/17 22:39
alog: est數平均的好幾倍 你就勢必要做調整 09/17 22:39
alog: 不論是利用 data/view/page cache 等 09/17 22:40
alog: AB 作法要看多利用 EXPLAIN 指令來看 SQL引擎怎麼解讀你的 09/17 22:41
alog: 指令 未必快或慢 09/17 22:41
alog: Query 越多意味著 application 跟 database server 之間的 09/17 22:42
alog: 傳輸封包量也會多 資料量也是 09/17 22:42
alog: 如果你的 query 結果沒有被 db query cache 起來其實也不會 09/17 22:42
alog: 快 不過有些情況是得關掉的 09/17 22:42
alog: 總之 如果你要單純比較 A 跟 B 我還是要先問 你的瓶頸在哪 09/17 22:43
alog: 裡 09/17 22:43
alog: 因為如果要做極致優化 有時候是連 select 的內容都會計較 09/17 22:45
alog: 但問題是 還是要回歸一開始 09/17 22:45
alog: 你的瓶頸在哪裡 有沒有要事先預防或安排 再來針對那個問題 09/17 22:46
alog: 做優化 而不是每頁都一定要做點什麼 09/17 22:46
alog: 只要掌握一個小規矩 就是別沒事搞出N+1的狀況就好 09/17 22:48
viper9709: 這個要看情況~不過一般來說A對DB的負擔比較輕 09/17 22:53
ernieyang09: 不複雜串幾張表sum一下的可以用B 要跨很多表統計的我 09/17 23:50
ernieyang09: 會選A orm裡面的select_related跟prefetch也看情況用 09/17 23:51
alan3100: 你一開始說分開query可以直接使用,且延伸問題看起來也沒 09/18 00:34
alan3100: join的必要. 除非你有要readlock不然沒必要一起拉 09/18 00:36
alan3100: with q_X as ( select ... from X where user_id=1) 09/18 00:47
alan3100: ,q_Y as ( select object_id, ... from Y 09/18 00:48
alan3100: where user_id=1 group by object_id) 09/18 00:48
alan3100: select * from q_X left join q_Y 09/18 00:48
alan3100: on q_X.object_id = q_Y.object_id 09/18 00:49
alan3100: 要硬湊大概就長這樣, executionplain理論上跟原本差不多 09/18 00:51
testPtt: 他的問題應該在於不知道怎麼接收多重select回傳的結果 09/18 09:23
testPtt: 所以用新手方法把select分批送出 這跟寫sql的功力無關了 09/18 09:26
abc0922001: 跟DB連線很貴的,次數要降到最小 09/18 10:51
alan3100: 那是沒用pool 。連這個都沒有就太誇張 09/18 11:12
srwhite: 不用考慮效能的情況下大家會不會覺得A比較好維護 09/18 12:09
asleepme: 我覺得我們需要DB專板 XD 09/18 12:12
stevekevin10: 一般狀況下請用2 09/18 12:17
BignoZe: 沒錯 有 connection pool 的情況下不會有 request 好幾次 09/18 21:40
BignoZe: 的問題 統計需求多變 執行次數不多 除非量真的大到跑不動 09/18 21:41
BignoZe: 的情況 可以用簡單的方法實作出來比較重要 09/18 21:42