请问这个 MYSQL 的语句,我应该如何优化或者建索引 - V2EX
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
ukipoi
V2EX    MySQL

请问这个 MYSQL 的语句,我应该如何优化或者建索引

  •  
  •   ukipoi 2024-04-10 10:44:35 +08:00 2642 次点击
    这是一个创建于 556 天前的主题,其中的信息可能已经有所发展或是发生改变。

    语句如下

    SELECT pni.parent_name, ni.name, dt.data_time, dt.value_a, dt.value_b FROM data_table dt LEFT JOIN rel_table rt ON dt.data_id = rt.rel_id LEFT JOIN name_info ni ON rt.rel_b_id = ni.rel_b_id LEFT JOIN parent_name_info pni ON ni.parent_id = pni.parent_id WHERE dt.data_time > ${dayTime} AND dt.data_time <= date_add(${dayTime},INTERVAL 1 DAY) AND pni.parent_id IN ( SELECT parent_id FROM parent_list) 

    mysql 的版本是 5.7 ,现在的情况是这个语句查询不出来。 数据表日期范围内的数据大概是不到 1W 条,rel 表中的数据不到 200 条。 ni 和 pni 这两个表中的数据可能有几十万条。

    19 条回复    2024-04-10 23:44:37 +08:00
    encro
        1
    encro  
       2024-04-10 10:46:32 +08:00
    explain 结果出来看下再说
    encro
        2
    encro  
       2024-04-10 10:47:37 +08:00
    dt 的 parnet_id 加 data_time 建立组合索引。
    Cruzz
        3
    Cruzz  
       2024-04-10 10:50:00 +08:00
    左关联会关联所有数据,形成大表再筛选,先筛选再关联减少连接数。你这数据量还没到扒着看的程度
    me1onsoda
        4
    me1onsoda  
       2024-04-10 11:04:02 +08:00
    以我浅薄的知识,恐怕没有什么好办法。我可能会把 pni.parent_id IN 这个 clause 放到表连接中,提高过滤率
    kwater
        5
    kwater  
       2024-04-10 11:08:18 +08:00
    IN (
    SELECT
    parent_id
    FROM
    parent_list)

    这个必须改 join ,否则你可能在某些人的偏执下会失去工作
    leon1900
        6
    leon1900  
       2024-04-10 11:09:29 +08:00
    parent_list 多少条数据
    ukipoi
        7
    ukipoi  
    OP
       2024-04-10 11:11:41 +08:00
    @encro
    结果是这个。

    id select_type `table` partitions `type` possible_keys `key` key_len `ref` `rows` filtered Extra
    1 SIMPLE rt ALL rel_id,data_id 187 100 Using where
    1 SIMPLE ni ref rel_id rel_id 111 test.rt.rel_id 1 100
    1 SIMPLE dt ref data_id,data_time data_id 110 test.rt.data_id 232 3.73 Using where
    1 SIMPLE pni ALL 96014 10 Using where; Using join buffer (Block Nested Loop)
    1 SIMPLE <subquery2> eq_ref <auto_key> <auto_key> 110 test.pni.parent_id 1 100
    2 MATERIALIZED parent_list index parent_id parent_id 110 185 100 Using index
    ukipoi
        8
    ukipoi  
    OP
       2024-04-10 11:12:07 +08:00
    @leon1900
    200 条不到
    qiqw
        9
    qiqw  
       2024-04-10 11:16:33 +08:00
    关注
    ukipoi
        10
    ukipoi  
    OP
       2024-04-10 11:16:46 +08:00
    @Richared 我试着把条件都写在 join 的表里了,最终结果大概是
    A ( 9000 ) B ( 200 ) C ( 200 ) D(50) 这 4 个表关联,还是出不来结果
    我看这 4 个表做全关联要 180W 数据了,mysql 会这样么。
    主要是之前用的都是 oracle ,自己数据库也不太行,oracle 关联好像可以直接出数据。
    Felix0504
        11
    Felix0504  
       2024-04-10 11:18:09 +08:00   1
    @ukipoi #7 你的 rt 和 pni 都是全表扫描,rt 数据量小也就算了,pni 数据量大,全表扫描肯定耗时,parent_id 加索引了吗
    elkfnmoyu
        12
    elkfnmoyu  
       2024-04-10 11:19:20 +08:00
    3 楼说的对,子查询里 data_time 先筛选 data_table 数据,然后再用子查询关联其他表
    leon1900
        13
    leon1900  
       2024-04-10 11:20:54 +08:00   1
    pni.parent_id 没索引吗
    ukipoi
        14
    ukipoi  
    OP
       2024-04-10 11:23:19 +08:00
    @Felix0504 没有单独的 parent_id 的索引,我加了结果就能出来了,谢谢!
    Cruzz
        15
    Cruzz  
       2024-04-10 11:27:58 +08:00
    @ukipoi 加个分页吧。
    Cruzz
        16
    Cruzz  
       2024-04-10 11:29:52 +08:00
    @ukipoi 这样的问题,首先考虑减小关联数,然后是否是全量返回,数据量大小多大,最后看你的条件走没走索引,尤其大表。你把条件写里边就是一个一个的简单查询,这个判断走不走索引,该怎么建立索引就简单多了,照着操作就行了。基本都能解决。
    fxjson
        17
    fxjson  
       2024-04-10 11:54:16 +08:00   1
    如果是我的话,首先 data_time 添加索引,
    其次 date_add(${dayTime},INTERVAL 1 DAY)去掉使用 date_add 函数,
    其次,子查询在应用中单独 sql 查询出结果然后用 in(xxx,xxx),
    最后看看 on 字段是否建立了对应的索引

    最后根据 explain 看结果进行分析是否有改进,如果上面几步都改了,sql 大概率不会有其他问题了
    encro
        18
    encro  
       2024-04-10 17:12:34 +08:00
    @ukipoi
    #7

    前有人提到过,就是 pni.parent_id 的问题,rows 96014 就它最大,且没有利用索引。
    给 pni.parent_id 建立索引就解决了。
    基本所有关联外键都需要建立索引的。
    tr>
    aliveyang
        19
    aliveyang  
       2024-04-10 23:44:37 +08:00
    pni.parent_id IN ()既然有这个条件了, LEFT JOIN 是不是没必要了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     884 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 22:16 PVG 06:16 LAX 15:16 JFK 18:16
    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