作者asleepme (500年没换昵称了)
看板Soft_Job
标题[请益] 一页的db query数
时间Mon Sep 17 12:39:31 2018
想请教一下,读取一页的时候 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://webptt.com/cn.aspx?n=bbs/Soft_Job/M.1537159174.A.125.html
1F:→ shvanta: 个人认为B的做法较好,一方面减少HTTP Request数,一方面DB 09/17 12:48
2F:→ shvanta: 对常用SQL,其实是有自己的机制让运行加快 09/17 12:49
3F:推 gmoz: 次数跟资料量之间的平衡 09/17 12:59
4F:→ alan3100: 会问这问题就选A. 你分不清楚A和B差异,选B对後人80%赛康 09/17 13:11
5F:推 oopFoo: 要B的话,就直接改用redis。以前是用memcached 09/17 13:11
6F:→ asleepme: 请教alan大,其中的差异跟B造成康的原因是什麽?感谢~ 09/17 14:32
7F:推 BignoZe: A 对 db 效能较好,B 可做的事情较多。 复杂的需求B,简 09/17 14:46
8F:→ BignoZe: 单的需求 A,试着用 explain 指令看看 db 实际搜寻的方法 09/17 14:46
9F:→ BignoZe: 和搜寻的资料笔数来判断。这边是如果资料量大才需要考虑 09/17 14:47
10F:→ BignoZe: 如果资料量小,过早的最佳化是一个反模式 09/17 14:48
11F:→ skitty: 可能出来ABCD 半年後说C资料有错 後人要连ABD一起看 09/17 14:49
12F:推 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
13F:→ testPtt: declare 去拆分需要的 少用多重join 09/17 15:02
14F:推 BignoZe: table设计怪怪的 table A user_id, object_id 是 uniq 09/17 19:36
15F:→ BignoZe: 那 table Y 可以直接关联 foriegn key x_id 09/17 19:37
16F:→ BignoZe: 这边统计要回归你的需求 你要统计的是什麽值 感觉上是可 09/17 19:38
17F:→ BignoZe: 先 join 再用 group 和 count 做运算 09/17 19:38
18F:→ BignoZe: 统计的话就不用管效能了 怎麽弄都是 slow query 09/17 19:39
19F:推 TAKADO: 通常是B,但没有标准答案吧,要看应用场景。B没写好很容易 09/17 20:55
20F:→ TAKADO: 让DB炸掉,尤其当join其中一张是上百万千万笔的资料表。 09/17 20:55
21F:→ asleepme: 感谢大家对db相关的指导~ 至於应用.. 刚刚改变了 XD 09/17 22:22
22F:→ alog: 基本上要看你的瓶颈是什麽 再来决定优化手段 09/17 22:36
23F:推 crossdunk: 看资料量吧 09/17 22:36
24F:→ alog: 如果那页是高流量 or 该页 request 数量1秒内是所有页面requ 09/17 22:39
25F:→ alog: est数平均的好几倍 你就势必要做调整 09/17 22:39
26F:→ alog: 不论是利用 data/view/page cache 等 09/17 22:40
27F:→ alog: AB 作法要看多利用 EXPLAIN 指令来看 SQL引擎怎麽解读你的 09/17 22:41
28F:→ alog: 指令 未必快或慢 09/17 22:41
29F:→ alog: Query 越多意味着 application 跟 database server 之间的 09/17 22:42
30F:→ alog: 传输封包量也会多 资料量也是 09/17 22:42
31F:→ alog: 如果你的 query 结果没有被 db query cache 起来其实也不会 09/17 22:42
32F:→ alog: 快 不过有些情况是得关掉的 09/17 22:42
33F:→ alog: 总之 如果你要单纯比较 A 跟 B 我还是要先问 你的瓶颈在哪 09/17 22:43
34F:→ alog: 里 09/17 22:43
35F:→ alog: 因为如果要做极致优化 有时候是连 select 的内容都会计较 09/17 22:45
36F:→ alog: 但问题是 还是要回归一开始 09/17 22:45
37F:→ alog: 你的瓶颈在哪里 有没有要事先预防或安排 再来针对那个问题 09/17 22:46
38F:→ alog: 做优化 而不是每页都一定要做点什麽 09/17 22:46
39F:→ alog: 只要掌握一个小规矩 就是别没事搞出N+1的状况就好 09/17 22:48
40F:→ viper9709: 这个要看情况~不过一般来说A对DB的负担比较轻 09/17 22:53
41F:推 ernieyang09: 不复杂串几张表sum一下的可以用B 要跨很多表统计的我 09/17 23:50
42F:→ ernieyang09: 会选A orm里面的select_related跟prefetch也看情况用 09/17 23:51
43F:→ alan3100: 你一开始说分开query可以直接使用,且延伸问题看起来也没 09/18 00:34
44F:→ alan3100: join的必要. 除非你有要readlock不然没必要一起拉 09/18 00:36
45F:→ alan3100: with q_X as ( select ... from X where user_id=1) 09/18 00:47
46F:→ alan3100: ,q_Y as ( select object_id, ... from Y 09/18 00:48
47F:→ alan3100: where user_id=1 group by object_id) 09/18 00:48
48F:→ alan3100: select * from q_X left join q_Y 09/18 00:48
49F:→ alan3100: on q_X.object_id = q_Y.object_id 09/18 00:49
50F:→ alan3100: 要硬凑大概就长这样, executionplain理论上跟原本差不多 09/18 00:51
51F:→ testPtt: 他的问题应该在於不知道怎麽接收多重select回传的结果 09/18 09:23
52F:→ testPtt: 所以用新手方法把select分批送出 这跟写sql的功力无关了 09/18 09:26
53F:推 abc0922001: 跟DB连线很贵的,次数要降到最小 09/18 10:51
54F:→ alan3100: 那是没用pool 。连这个都没有就太夸张 09/18 11:12
55F:推 srwhite: 不用考虑效能的情况下大家会不会觉得A比较好维护 09/18 12:09
56F:→ asleepme: 我觉得我们需要DB专板 XD 09/18 12:12
57F:推 stevekevin10: 一般状况下请用2 09/18 12:17
58F:推 BignoZe: 没错 有 connection pool 的情况下不会有 request 好几次 09/18 21:40
59F:→ BignoZe: 的问题 统计需求多变 执行次数不多 除非量真的大到跑不动 09/18 21:41
60F:→ BignoZe: 的情况 可以用简单的方法实作出来比较重要 09/18 21:42