V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
cevincheung
V2EX  ›  MySQL

你会选择连表查询速度一般还是拆成多次查询速度飞快的数据库查询方法?

  •  
  •   cevincheung ·
    cevin · 2015-06-04 04:58:04 +08:00 · 23136 次点击
    这是一个创建于 3464 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如:

    select from a join b on a.x=b.x left join c on a.x=c.x

    还是
    select id from a
    程序获取ids
    select b where id in (ids)
    select c where id in (ids)

    第 1 条附言  ·  2015-06-04 12:20:13 +08:00
    主要想问的是对于一些大表查询、关联索引设计的不好的情况- -#
    第 2 条附言  ·  2015-06-04 12:28:58 +08:00
    还想多嘴一句,如果条件太多的话,而且还加上排序,是不可能会优化好索引的吧?
    比如:商品属性条件检索加上价格区间(打个比方,不用提elastic啥的
    第 3 条附言  ·  2015-06-04 12:30:24 +08:00
    关于网络,我现在用第二种方法进行查询,在青云和美团云分别挂了db和web。在美团机器上开了个Pgpool本地连接本地的pgpool速度还是可以的。网络延时没多大啊
    41 条回复    2015-12-02 17:19:32 +08:00
    lightening
        1
    lightening  
       2015-06-04 05:16:52 +08:00
    连成一条。数据库和应用有时候不在一个机器上,网络延迟比较大。
    cevincheung
        2
    cevincheung  
    OP
       2015-06-04 05:21:43 +08:00
    @lightening 一般都会在同一内网吧
    lightening
        3
    lightening  
       2015-06-04 05:40:59 +08:00
    @cevincheung 我们不是的。
    CupTools
        4
    CupTools  
       2015-06-04 05:42:56 +08:00
    连表,有时还会连4表查。
    这是我上课的时候其中一条SQL:
    SELECT Count(*) AS S_NAMEOfCount, supplier.s_nationkey,
    nation.n_name
    FROM (SELECT DISTINCT supplier.s_name,
    supplier.s_nationkey,
    nation.n_name
    FROM (region
    INNER JOIN ((customers
    ey =
    = orders.o_custkey)
    gionkey)
    INNER JOIN nation
    ON customers.c_nationk
    nation.n_nationkey)
    INNER JOIN orders
    ON customers.c_custkey
    ON region.r_regionkey = nation.n_re
    INNER JOIN supplier
    ON nation.n_nationkey = supplier.s_n
    ationkey)
    GROUP BY supplier.s_nationkey,
    nation.n_name;
    Septembers
        5
    Septembers  
       2015-06-04 05:51:15 +08:00 via Android
    @lightening @cevincheung
    即使是内网也不敢链路质量100%稳定
    (QoS策略没做好导致链路质量下降之类的事情(这是网络运维的锅
    liprais
        6
    liprais  
       2015-06-04 07:20:56 +08:00
    三次查询的总时间肯定比一次的大吧
    wy315700
        7
    wy315700  
       2015-06-04 07:41:40 +08:00
    分开查询何必用sql,用key value多好
    zkd8907
        8
    zkd8907  
       2015-06-04 07:54:12 +08:00
    @cevincheung 就算在内网上,网络IO成本也是比数据库服务器本地的IO成本要高的。。。(不要问我为什么知道的。。
    clino
        9
    clino  
       2015-06-04 08:10:18 +08:00
    @zkd8907 我觉得你说的即使是对本机的数据库也是对的
    mawenjian
        10
    mawenjian  
       2015-06-04 08:21:48 +08:00
    分情况,强关联的表采用联表查询;如果关联性不是那么强的话,老老实实分步查,要不哪天拆库还得重写。
    yangqi
        11
    yangqi  
       2015-06-04 08:24:15 +08:00
    只要索引什么的优化好,联表一次肯定比多次要快的
    dai269619118
        12
    dai269619118  
       2015-06-04 08:46:01 +08:00
    放数据里跑一下不就知道效率了吗
    lucifer9
        13
    lucifer9  
       2015-06-04 08:48:53 +08:00
    考虑到缓存的情况呢
    caixiexin
        14
    caixiexin  
       2015-06-04 09:00:26 +08:00
    数据库优化的一个原则就是查询次数越少越好,特殊的复杂sql语句除外。很多情况下网络开销,使用数据库链接都比劣质sql语句开销大。
    lengxuecan
        15
    lengxuecan  
       2015-06-04 09:13:48 +08:00
    绝逼拆分写!没有之一!
    spkinger
        16
    spkinger  
       2015-06-04 09:14:32 +08:00
    不连表,用union把几个sql连起来试试
    sujin190
        17
    sujin190  
       2015-06-04 09:18:46 +08:00
    如果数据有几百万你join一次试试
    anyforever
        18
    anyforever  
       2015-06-04 09:23:58 +08:00
    @yangqi +1 关键是索引得优化好
    jsuper
        19
    jsuper  
       2015-06-04 09:38:44 +08:00
    如果索引设计得好,两边关联的字段都有索引,那么关联是很快的。远比你分多次查询要来得快。
    lzsadam
        20
    lzsadam  
       2015-06-04 10:25:54 +08:00
    单表,遇到复杂的查询条件就跪了,代码维护起来累死
    songw123
        21
    songw123  
       2015-06-04 10:47:56 +08:00
    看情况,在实际环境中比较一下就行了,第一是速度,第二是数据库压力,第三是使用频度,选择最合适的就好,不过整体来说,很少用join了
    lbp0200
        22
    lbp0200  
       2015-06-04 11:15:36 +08:00
    如果数据库在内网,每次查询几百兆的数据,你就知道应该怎么做了。
    zonghua
        23
    zonghua  
       2015-06-04 11:41:05 +08:00 via iPhone
    a join b和where condition 有什么不同?
    yangqi
        24
    yangqi  
       2015-06-04 12:20:30 +08:00
    @zonghua 没有不同,不过where只能join两个表,而且只能inner join
    yangqi
        25
    yangqi  
       2015-06-04 12:23:06 +08:00
    如果没办法优化关联索引那只能拆分查询了,不过说过了速度肯定没有优化过关联索引得快。

    所以自己根据情况看着办吧
    RemRain
        26
    RemRain  
       2015-06-04 12:28:25 +08:00
    如果 in 的集合不是特别大的话,习惯拆开来查询。前端扩容加机器就行;把各种处理和计算都压在数据库上的后果是,万一数据库抗不住,要扩容就吐血了
    ivvei
        27
    ivvei  
       2015-06-04 12:48:07 +08:00
    @sujin190 你分步查出来了还不是得自己join。就实际查询量来说,你分步需要的数据还比join好了的多。
    ivvei
        28
    ivvei  
       2015-06-04 12:51:20 +08:00
    楼主你这两种查询不等价。一个是横的,一个是竖的。
    cevincheung
        29
    cevincheung  
    OP
       2015-06-04 12:58:17 +08:00
    @CupTools

    关联的几个表分别多少数据,并且表结构方便贴一下吗?或者看一下explain
    pubby
        30
    pubby  
       2015-06-04 13:01:28 +08:00
    @RemRain 同意

    如果考虑到后期加入cache层的话,不join。
    个人只在一些管理后台才会用复杂sql查询

    另外 where in 在表上了百万级别后性能有问题
    where in (1,2,3) 还不如 where id=1 union ... where id=2 union ... where id=3 快得多
    当然list如果很长,需要另外想办法优化
    cevincheung
        31
    cevincheung  
    OP
       2015-06-04 13:09:26 +08:00
    @pubby
    为何我想到了exists :any
    sujin190
        32
    sujin190  
       2015-06-04 13:40:18 +08:00
    @ivvei 可是设计良好的话,单步的数据应该是非常小的,而且内网的话网络延迟应该在数毫秒内吧,就算单步十次也几十毫秒,而且相对来说是个稳定值
    hylent
        33
    hylent  
       2015-06-04 17:29:55 +08:00   ❤️ 1
    那么多join的话,基于主键的cache怎么用?
    水平sharding之后,还怎么join?
    每次查询几百兆的数据,这是在做啥么……,反正肯定不是web了吧?
    cevincheung
        34
    cevincheung  
    OP
       2015-06-04 17:31:40 +08:00
    @hylent so,你更倾向后者么?
    hylent
        35
    hylent  
       2015-06-04 17:45:28 +08:00
    @cevincheung
    对,倾向后者。
    但是有的时候,join是必须的,有些需要跨表的条件,只能join啊啊
    ivvei
        36
    ivvei  
       2015-06-05 11:55:22 +08:00
    @sujin190 比如 select * from a join b on a.aid = b.bid. 拆成两步就是 select * from a 和 select * from b。
    原本返回的结果集是交集,现在需要把两表的数据都传回来。这个数据量明显是增大了很多的。返回来之后还没完,你还得在本地再进行人肉匹配,找一种算法来把两次返回的内容中相同的部分找出来。


    除非考虑对前端进行水平扩展降低数据库单点压力,我没看到使用单步的方式有多大好处。
    cevincheung
        37
    cevincheung  
    OP
       2015-06-05 12:06:54 +08:00
    @ivvei

    ids = select b_id from b where condition xxxxx
    data = select a_field from a where ids in (ids)


    如果仅仅是select没有条件检索那肯定前者更好的
    bash99
        38
    bash99  
       2015-06-05 16:40:22 +08:00
    觉得第二种快的基本上是带排序之后,只需要TOP N结果的吧。
    正常情况下第一种肯定比第二种快。
    ivvei
        39
    ivvei  
       2015-06-09 19:40:19 +08:00
    @cevincheung 即便是带有条件的,你先查出id再查data,一样要多来回传一份id的数据。另外你修改了查询的内容。原本我举的例子里,所需要的data包含a,b两个表的数据。你现在这种情形只有表a的数据了。像这样的句子,你直接写 select a_field from a where ids in (select b_id from b where condition xxxxx) 也已足够,数据库的优化引擎选择的查询算法只会做得比你更好不会做得比你更差。
    ivvei
        40
    ivvei  
       2015-06-09 19:42:16 +08:00
    @cevincheung one more thing, 有些数据库里, in 后面直接接 (id1,id2,id3...) 是有个数限制的。比如Oracle…… 限定1000个。超过1000就会出问题。而接一个子查询就没问题。
    ben548
        41
    ben548  
       2015-12-02 17:19:32 +08:00
    其实我也很好奇,不过这里的讨论好像没有给出一个很明确的答案,我在工作中为了避免写复杂的 sql 语句,通常使用第二种方式,不过个人感觉第二种查询方式比较慢啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1563 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 23:58 · PVG 07:58 · LAX 15:58 · JFK 18:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.