V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
awanganddong
V2EX  ›  编程

where in 和 where not in 怎么优化

  •  
  •   awanganddong · May 22, 2021 · 2298 views
    This topic created in 1805 days ago, the information mentioned may be changed or developed.

    1.业务场景,在用户表查询这个用户的好友。 2.业务场景,查出除黑名单的所有人。

    好友和黑名单人数都在几千人。

    14 replies    2021-05-24 21:46:03 +08:00
    yungo8
        1
    yungo8  
       May 22, 2021 via Android
    我觉得黑名单是好友中加了状态的一类
    xy90321
        2
    xy90321  
       May 22, 2021 via iPhone
    SQL 层面感觉没什么好优化的
    如果你想减轻 DB 压力,就把除去黑名单联系人的逻辑搬去 BL 做
    如果你想减轻服务器压力,那就搬去客户端做
    yitingbai
        3
    yitingbai  
       May 22, 2021
    我也在头疼 in 的问题, 但是又没有别的好办法, 只能 in
    nine
        4
    nine  
       May 22, 2021
    好友和黑名单不是在中间表里存着的么?为什么要 in 呢?
    awanganddong
        5
    awanganddong  
    OP
       May 22, 2021
    就比如我想从用户表里边匹配合适的用户,这时候就要剔除黑名单等不符合用户。
    而且不单单这两个地方,
    许多地方都需要 in
    BeautifulSoap
        6
    BeautifulSoap  
       May 22, 2021 via Android
    你好友黑名单数据难道是放在数据库之外的只能先获得好友 id 列表,然后 where in ?
    还是说表设计有问题?一般我觉得好友关系和黑名单信息是分开放在两个表里(或者单个表里有个字段标注是不是拉黑),想获得没有黑名单用户的信息的话,直接从好友那个表 join 不就行了,也用不到 in 的操作啊
    还有一点是你真的需要一次性搜出几千个用户数据吗?做数据分析还能理解,如果拿来做网页或给 app 提供数据,你根本用不着直接把所有数据都一次性搜出来吧
    512357301
        7
    512357301  
       May 22, 2021 via Android
    @awanganddong 有没有测试过 left join ?
    根据你的描述,好友表是包含黑名单的数据的,那最快的方法就是好友表再加个黑名单字段用来标识出黑名单状态,这样直接 where 约束就行。
    在没有黑名单字段的前提下,可以考虑 left join,左连接以后,再在 where 里约束右表等于 null 那部分,这样左表里剩下的数据就是所需的了。
    select a.id from a --好友表
    left join b on a.id=b.id --黑名单表
    where b.id is null
    我是数据出身,没想过用 java 或者 php 之类的编程语言会不会更快,单纯用 sql 实现的话也就是这个思路了,我个人比较抵触在 in 里套子查询
    awanganddong
        8
    awanganddong  
    OP
       May 22, 2021
    比如现在要查询其他在线用户。
    那我首先获取到这个用户的黑名单 uidArr,
    然后拿着这个 uidArr 去 where not in 去剔除这些用户(对于这个用户黑名单可能有几千的数据)

    ----------------
    用户会话列表,客户端是把聊天用户的唯一标识给我,
    然后我去 where in 这些标识 去获取这些列表
    BeautifulSoap
        9
    BeautifulSoap  
       May 23, 2021 via Android
    @awanganddong 把你相关表结构说一下,光你这文字描述根本猜不出来你表怎么建的,搞不懂你为什么需要先查到用户的黑名单 id 数组

    你的 好友关系表 的结构难道是 user_id friend_id 两个字段?然后黑名单则是通过 string 格式的数组直接保存在 用户信息表 的一个字段里?
    awanganddong
        10
    awanganddong  
    OP
       May 23, 2021 via Android
    不知道你用过陌陌没有,陌陌有附近的人。然后我把这个用户加黑名单了,那在附近的人这个列表里边就不能出现,类似这样的业务需求。
    一张 user 表 id
    一张 user_blacklist 表 id uid
    c6h6benzene
        11
    c6h6benzene  
       May 23, 2021 via iPhone
    @awanganddong blacklist 表里面的 uid 就是被黑名单那个用户的 id 吗?

    如果“附近的人”也是一张表的话(里面有 id ),那就用 uid left join 这张表的 id,取 join 结果为 null 的好了。

    另外也可以试试 exists
    awanganddong
        12
    awanganddong  
    OP
       May 23, 2021
    单纯靠 mysql 已经解决不了这个问题了


    exists 和 union all 都用了 , 好不如原来的 where in 的性能
    zm8m93Q1e5otOC69
        13
    zm8m93Q1e5otOC69  
       May 23, 2021
    直接用代码实现会不会快一些捏?
    awanganddong
        14
    awanganddong  
    OP
       May 24, 2021
    想到一种思路

    where in ID 分段,然后我起多个线程或者多个携程并发请求。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   921 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 123ms · UTC 23:21 · PVG 07:21 · LAX 16:21 · JFK 19:21
    ♥ Do have faith in what you're doing.