请教 DBA 一个小白问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chaleaochexist
V2EX    数据库

请教 DBA 一个小白问题

  •  
  •   chaleaochexist 2024-09-05 00:18:12 +08:00 2917 次点击
    这是一个创建于 475 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题 1,

    from a left join b on a.id=b.fid where a.id=10 

    像这种是先 where 还是先 join? 还是数据库会根据它自己的判断进行优化?

    问题 2,

    select a.*,b.* from a left join b on a.d=b.fid order by a.id limit 10 

    SELECT a1.*, b.* FROM ( SELECT * FROM a ORDER BY a.id LIMIT 10 ) AS a1 LEFT JOIN b ON a1.id = b.fid; 

    这两句话是不是执行效率是一样的?

    你们在实际工作中遇到类似的场景多吗? 会纠结用哪种 sql 吗?

    16 条回复    2024-09-05 11:37:45 +08:00
    Ricebucket
        1
    Ricebucket  
       2024-09-05 00:52:37 +08:00
    dba 会管这些?
    R4rvZ6agNVWr56V0
        2
    R4rvZ6agNVWr56V0  
       2024-09-05 01:44:13 +08:00
    使用 EXPLAIN 查看 SQL 查询的执行计划,便知。通常会被自动优化。

    假如 a 表 b 表很大,子查询这段 SQL 性能通常高一些,关键因素:LIMIT 。

    对 LIMIT 解释:
    在单表查询这段 SQL 中,LIMIT 位于 ORDER BY 之后,只取连接后排序后的前 10 条记录。
    在子查询那段 SQL 中,LIMIT 位于子查询内部,只取 a 表排序后的前 10 条记录传递给外层查询。
    levelworm
        3
    levelworm  
       2024-09-05 07:48:44 +08:00 via Android
    Explain 一下就行了。一般优化的都很不错的。
    a1b2c3T
        4
    a1b2c3T  
       2024-09-05 08:48:51 +08:00
    问题 1 应该是先 join 再 where
    MozzieW
        5
    MozzieW  
       2024-09-05 09:12:56 +08:00   1
    @a1b2c3T 测试加上问 GPT ,至少在我有索引等情况下,会先执行 where 再 join 。下面是 GPT 的解释:

    ```
    理论上:SQL 语句的执行顺序是先 FROM 、再 JOIN 、最后 WHERE 过滤。
    实际执行:数据库查询优化器可能会调整顺序,尽量减少数据处理的开销(比如尽可能早地应用 WHERE 过滤条件)。
    ```
    a1b2c3T
        6
    a1b2c3T  
       2024-09-05 09:15:55 +08:00
    @MozzieW #5 我记着前几年优化 sparksql 的时候这种问题还挺多的,那会儿一个优化点就是提前过滤表数据,可能数据库底层优化方式不一样吧。mysql 和 oracle 不知道会不会优化
    MozzieW
        span class="no">7
    MozzieW  
       2024-09-05 09:34:08 +08:00
    @a1b2c3T #6 是的,补充一下,我测试的是 MySql 。
    这个属于具体的优化,不同的数据库实现不一样。
    另外,这里只有一个主表的 where ,如果是多个表,结果可能不一样,不能理解为一定先执行 where 再执行 join
    andykuen959595
        8
    andykuen959595  
       2024-09-05 09:36:57 +08:00
    这种 直接开跑起来 再看 要切合实际环境
    qW7bo2FbzbC0
        9
    qW7bo2FbzbC0  
       2024-09-05 09:42:16 +08:00
    1.按语法来说是 先 join 后 where
    2.具体表格具体分析,看 explain 结果
    xlzyxxn
        10
    xlzyxxn  
       2024-09-05 09:56:37 +08:00
    mysql 连接查询用的是嵌套循环算法,你这几个 sql 都是左连接或者右连接,驱动表和被驱动表已经确定了;你需要的是为每个表选择成本最低的访问方案;问题 1 问的没太懂,看看嵌套循环执行的步骤你可能就懂了;问题 2 第二种把驱动表缩小到了 10 条记录,扇出次数比第一种要少(在 mysql 没对第一种做优化的时候),效率肯定高,具体执行时 mysql 到底对第一种 sql 做没做优化这个就不清楚了
    ZZ74
        11
    ZZ74  
       2024-09-05 10:01:44 +08:00   1
    没特意查过,根据过往经验
    A1 先 join ,但是实际性能和你 on on a.id=b.fid and a.id=10 这样的写法性能是一样的。就是数据库会优化
    A2 绝大多数情况下,后者可以确保效率至少和前者一样,但是数据库可能会优化,取决于数据量和数据库类型。
    sagaxu
        12
    sagaxu  
       2024-09-05 10:20:52 +08:00   1
    第一个问题,数据库一般会自己优化
    https://dev.mysql.com/doc/refman/8.4/en/condition-filtering.html

    第二个问题,第 2 个查询效率 >= 第 1 个,看 DB 的优化
    kosmgco
        13
    kosmgco  
       2024-09-05 10:29:20 +08:00
    问题 1: 等值传递,优化器会拆成两个子查询 [from a where id = 10, from b where fid = 10],先 where 再 join 能少很多 io

    问题 2:如果 a 数据量比较大,第二种方式左表的数据量会大大减少,会比第一种方式更快,

    但是两种方式的结果不一样,第一种方式是先 join 再 order by 再 limit ,最终结果 10 条是确定的,第二种方式结果条数就不一定了
    chaleaochexist
        14
    chaleaochexist  
    OP
       2024-09-05 11:27:53 +08:00
    @kosmgco 确实, 第二种情况, 假设是一一对应的.
    在开发的过程中, 会扣这种小细节吗?
    还是把这种优化交给数据库,相信数据库会处理.
    chaleaochexist
        15
    chaleaochexist  
    OP
       2024-09-05 11:30:19 +08:00
    @ZZ74 第二个问题, 在实际开发过程中, 您会扣这种小细节还是选择相信数据库?
    ZZ74
        16
    ZZ74  
       2024-09-05 11:37:45 +08:00   1
    我应该会直接用第二种写法,很可能第一种都不会出现在脑袋里。因为对我来说第二种更符合逻辑
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2838 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 92ms UTC 14:21 PVG 22:21 LAX 06:21 JFK 09:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86