A 表 40w 数据 B 表 42W 左右, A 和 B 是一对多的关系,现在需要分页查询所以如果用 Aleft join B 数据会变多,group by 的话速度很慢, 目前用的 select * from A where exists ( select 1 from B where a.order_id = b.order_id ) 页面有些查询条件存在 A 有的存在 B ,查询条件速度很慢,B 的查询条件页面响应速度在 6s 左右,看 sql 执行需要 2.5s
1
fengpan567 118 天前
不要用子查询,用 join B ,再加个<if>条件判断,如果没有 B 的查询字段,直接跳过 join 只查 A 表
|
2
ZZ74 118 天前
查询条件只有 order_id ?优化 sql 不如优化索引
|
3
Geon97 118 天前
数据库架构是什么?什么索引?什么引擎? group by 的字段是索引吗?使用 join 的方式呢?
|
4
jov1 118 天前
这个要看具体情况,比如你查出来的列表不需要 b ,只需要 a 的字段,可以考虑下面这两种,结合执行计划看下索引命中情况。如果 ab 联表查询慢,但是单独查 b 的情况不慢,也可以程序中先单独根据条件查符合 b 的 order_id 再执行 a 的查询
select distinct a.xx, a.xx,a.xx from a join b on a.order_id = b.order_id where a.xx = ? and b.xx=? 或者 select a.xx, a.xx,a.xx from a where a.order_id in ( select order_id from b where order_id is not null and xxx=? and xxx=? ) |
5
Vesc OP @fengpan567 #1 多数的情况 A 和 B 都有查询条件
|
9
jov1 118 天前
@Vesc 如果打算程序先查 B ,然后再查 A ,这个没关系,比如原来可能是这样
select a.row1 ,a. row2 from a join b on b.order_id = a.order_id <where> <if test="name != null and namelength()>0"> </where> where 那你程序无非就是先一天 sql 查询 |
10
venicid 118 天前
我们经常这么使用,仅供参考
select * from ( select * from A where A.xx = xxx ) as t left join b on t.order_id = b.order_id |
11
jov1 118 天前
@Vesc 如果打算程序先查 B ,然后再查 A ,这个没关系,比如原来可能是这样
select a.row1 ,a. row2 from a join b on b.order_id = a.order_id <where> a.age > 18 <if test="name != null and namelength()>0"> and (a.name = 'xx' or b.name = 'xx') </if> </where> 那你程序就是先单独查 b 的,比如 name 是需要 ab 表都查的,,再将这个 orderIds 作为条件二次查询 a 如果 name 不为空的情况下,就先查 b ,然后返回 order_id(看你描述,ab 是通过 order_id 关联的) select order_id from b where .name = 'xx' 然后 select a.row1 ,a. row2 from a <where> a.age > 18 <if test="name != null and namelength()>0"> and (a.name = 'xx' or a.order_id in <if test="orderIds != null and orderIds.size() > 0"> <foreach collection="orderIds" item="orderId" separator="," open="(" close=")"> #{orderId,jdbcType=BIGINT} </foreach> </if> ) </if> </where> |
12
flyfanc 118 天前
可能是 mysql 优化的锅,慢的时候执行一下 analyze table 有奇效
|
14
Gravitysrainbow 118 天前
where exists ( select 1 from B where a.order_id = b.order_id )
|
15
Gravitysrainbow 118 天前
where exists ( select 1 from B where a.order_id = b.order_id )这是个相关子查询,执行慢是因为 B 的查询依赖于 A 的结果,这个时候会先执行 A ,如果 A 的结果剩下 20w ,B 的子查询就要执行 20W 次,可以参考这个文档: https://blog.csdn.net/weixin_43997319/article/details/123713513 ;最简单的优化方案就是使用 join: select
A.* from A inner join ( select A.id from A left join ( select 1 from B where ) BX ON a.order_id = b.order_id <where> <if test="name != null and namelength()>0"> </where> ) AX on AX.id = A.id where 1=1 |
16
Gravitysrainbow 118 天前
要确保 select A.id
from A 以及 select 1 from B where 这两个单独的子 sql 都能命中索引,命中 后获取到 A 的 ID ,在 inner join 一次手动回表去重,可以避免在 sql 里 distinct 或者 group by 的开销 |
17
cccvno1 118 天前
建议先分析 sql 的执行计划,再去执行优化。相同的查询在不同版本不同配置下都可能会出现不同的执行计划
|
18
wenxueywx 118 天前
#15 似乎可行,值得尝试,欢迎 op 测试后回复一下
|
19
Vesc OP @Gravitysrainbow #15 感谢大佬我取测试一下速度
|
22
andytao 118 天前
2.5s 对于数据量大、网络状态不好的话,算正常吧。
需要进一步确认时间卡在哪里: 连接?索引?数据汇合?数据传输?客户端显示? |
23
MoYi123 118 天前
把 explain 贴出来看看, 如果里面有 hash semi join ,那就说明是机器性能太差了, 否则就是 sql 要改.
|
24
nianlifeixing 118 天前
exists 不一定最优,A exists B ,A 的数据量大,不要考虑 exists ,大多数情况下一定有条件,不可能查询所有有关联的 A 的信息,可能 A 的数据量有 20w ,不可能统一都给前端把,还是得看场景
|
26
tbv 118 天前
子查询还不如 join 呢
|
27
xiaohang427 118 天前
可以贴下 SQL ,我现在用 PG ,交易表大概 4000W 条数据,有个终端表大概几 W ,也是用 JOIN 方式。后来想改为 IN 条件,但是条件太多会造成索引失效。还是要具体问题具体对待
|
28
KOMA1NIUJUNSHENG 118 天前
先查 id 集合,再用 id 查完整数据
|
29
zemo 118 天前
分页查询,有 limit,关联字段有索引应该不会慢呀, 主要就是查处满足条件的 a 数据再做关联,避免全量关联就会快很多,确认走到索引了吗?
|
30
aw2350 118 天前
|
31
Xrall 118 天前
|
32
rm0gang0rf 118 天前
A 订单 240w, B sku 720w, 比你慢点
|
33
wangritian 118 天前
A 表加字段缓存 where exists ( select 1 from B where a.order_id = b.order_id )的结果如何?
|
35
justNoBody 118 天前
我尝试自己建了一个 OP 说的数据场景( 40w+42w 做 left join 和 group by ),但是我秒出,ms 级。
OP 看看能不能造个数据库发出来吧,把数据脱敏一下或者是重新跑一个新的库表 |
36
a7851578 117 天前
不给表结构和索引,还有 explain 怎么建议
|