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

请教 DBA 一个小白问题

  •  
  •   chaleaochexist · 112 天前 · 2313 次点击
    这是一个创建于 112 天前的主题,其中的信息可能已经有所发展或是发生改变。

    问题 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.id=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  
       112 天前
    dba 会管这些?
    GeekGao
        2
    GeekGao  
       112 天前
    使用 EXPLAIN 查看 SQL 查询的执行计划,便知。通常会被自动优化。

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

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

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

    第二个问题,第 2 个查询效率 >= 第 1 个,看 DB 的优化
    kosmgco
        13
    kosmgco  
       111 天前
    问题 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
       111 天前
    @kosmgco 确实, 第二种情况, 假设是一一对应的.
    在开发的过程中, 会扣这种小细节吗?
    还是把这种优化交给数据库,相信数据库会处理.
    chaleaochexist
        15
    chaleaochexist  
    OP
       111 天前
    @ZZ74 第二个问题, 在实际开发过程中, 您会扣这种小细节还是选择相信数据库?
    ZZ74
        16
    ZZ74  
       111 天前   ❤️ 1
    我应该会直接用第二种写法,很可能第一种都不会出现在脑袋里。因为对我来说第二种更符合逻辑
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1167 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:24 · PVG 02:24 · LAX 10:24 · JFK 13:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.