› 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
Amber2011
V2EX  ›  MySQL

一次查询 n 条数据和查询一条数据重复 n 次的区别和影响?

  •  
  •   Amber2011 · Aug 29, 2021 via Android · 4185 views
    This topic created in 1853 days ago, the information mentioned may be changed or developed.

    假设有一个 user 表,{id,name,phone},要根据名字(可能会传很多个)查询 user 的 id 和 phone,一次性查询全部然后转换成{name,user}的 map 匹配好还是每次都去查一次数据库然后 where name = xxx 好?

    是否存在一个大概的数量值,来作为这两种方式的分界线?

    14 replies  •  2021-09-16 19:45:48 +08:00
    ipwx
        1
    ipwx  
       Aug 29, 2021   ❤️ 1
    前一个没看懂。

    标准操作我觉得是建个临时表,把想差的名字都写进去,然后用 JOIN 。
    ipwx
        2
    ipwx  
       Aug 29, 2021
    ps 临时表是 connection-only in-memory 的
    ravelminerva
        3
    ravelminerva  
       Aug 29, 2021
    我觉得你可以做一个测试。
    BigDataIsDead
        4
    BigDataIsDead  
       Aug 29, 2021 via iPhone   ❤️ 1
    终于遇到个能答上来的问题了

    具体得看你说的 “好”怎么定义
    “空间好”:那当然是直接去数据库查
    “时间好”:缓存到应用里?或者外部应用做缓存?

    比较“好”的做法是对 user 表做缓存,一旦对用户表做了任何 crud 操作,删除相对应的键重新插入,空档期缓存没命中再走 SQL DB,不过得具体情况具体分析。

    之前做的 OA 也有这个问题,子部门多父部门广,树状表结构走 Oracle 在测试环境下面奇慢无比,上面不让用 Redis,没办法,只能把对应权限的数据写进 session 里,登陆给他存一下,好在用户量不多,还能撑住。
    CEBBCAT
        5
    CEBBCAT  
       Aug 29, 2021
    不能保证 user 的 name 唯一,所以建议按照模糊查询的方式做:WHERE name IN ('alice', 'bob')
    Amber2011
        6
    Amber2011  
    OP
       Aug 29, 2021
    @ipwx 第一个就是直接查全表,然后把结果转换为 Map(代码层面),key 是 name,value 是对象. 然后去判断这个 map 里是否存在指定的 name.
    第二种就是传入多少个 name 就查多少次
    一开始写的第一种,然后被吐槽说如果查出来的数据量太大(同时需要查询的量不算多)还不如一个一个查
    Hurriance
        7
    Hurriance  
       Aug 29, 2021
    @Amber2011 第一种做法即可吧,我不太理解,是不是无论怎么样都需要找到同样的记录呢
    fkdog
        8
    fkdog  
       Aug 29, 2021
    当然是能一次取完的就不要取 N 次了。
    for 循环难道就能节省数据量了?你同事吐槽你他自己也是个半桶水。
    opengps
        9
    opengps  
       Aug 29, 2021
    取决于业务要求:
    一次取大量数据用的 in 的写法是很不利与索引的,单好处是可能只有一次 io 。
    逐条取很多次数据好处往往是索引到位。单个获取很快,但是缺点也很明显就是 io 次数明显太多了。
    建议做成分页类的逻辑
    BiteTheDust
        10
    BiteTheDust  
       Aug 29, 2021
    一次查询多个能省 IO 索引的话看具体情况了 还是有机会能命中一些的
    ipwx
        11
    ipwx  
       Aug 29, 2021
    @Amber2011 你没理解我说的。

    你这个问题没说清楚的一个点是,假设表里有 N 个用户,你每次要查的用户数量 k,到底是远小于 N 还是等于 N ?

    如果 1 < k << N,那么就用临时表存储你要查的用户名,然后用 JOIN 从主表得到所有需要的结果。
    ipwx
        12
    ipwx  
       Aug 29, 2021   ❤️ 1
    哦顺便如果只是三五个那写个 IN 就行了。

    子表说的是 30 50 乃至 300 500 个要查的用户名,但是总表可能有 30 50 万个用户这种情况。
    LearnFeedback
        13
    LearnFeedback  
       Aug 30, 2021
    1 、前一种情况实际上是做了本地的缓存
    Aresxue
        14
    Aresxue  
       Sep 16, 2021
    要看预估数据量喽,第一种 in 在 name 超大的情况下会造成 sql 语句超过 max_allowed_packet, 而且不利于做缓存优化,还有可能因为单次数据量过大撑爆,第二种就是单次连接只查一条数据过于浪费,可以折中一下, 分析下 name 的 Cardinality, 然后一批 name 过来将其拆分为几个小集合,单个集合按照 cardinality 的预估最终维持查出的数据量单次在指定大小(如 1000)左右,然后在内存里拼接数据, select 语句的开销除了 query 还有 fetch 和 transport, 多线程去做一批的查询最后汇总一般比大结果集单次查询会快上一些。最后说一句如果不是 p0 级接口且有性能诉求不要进行上述优化。。。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2373 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 10:37 · PVG 18:37 · LAX 03:37 · JFK 06:37
    ♥ Do have faith in what you're doing.