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

where in 和 where not in 怎么优化

  •  
  •   awanganddong · 2021-05-22 21:36:52 +08:00 · 1877 次点击
    这是一个创建于 1300 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    14 条回复    2021-05-24 21:46:03 +08:00
    yeqizhang
        1
    yeqizhang  
       2021-05-22 21:39:35 +08:00 via Android
    我觉得黑名单是好友中加了状态的一类
    xy90321
        2
    xy90321  
       2021-05-22 21:50:23 +08:00 via iPhone
    SQL 层面感觉没什么好优化的
    如果你想减轻 DB 压力,就把除去黑名单联系人的逻辑搬去 BL 做
    如果你想减轻服务器压力,那就搬去客户端做
    yitingbai
        3
    yitingbai  
       2021-05-22 22:00:58 +08:00
    我也在头疼 in 的问题, 但是又没有别的好办法, 只能 in
    nine
        4
    nine  
       2021-05-22 22:31:21 +08:00
    好友和黑名单不是在中间表里存着的么?为什么要 in 呢?
    awanganddong
        5
    awanganddong  
    OP
       2021-05-22 22:43:07 +08:00
    就比如我想从用户表里边匹配合适的用户,这时候就要剔除黑名单等不符合用户。
    而且不单单这两个地方,
    许多地方都需要 in
    BeautifulSoap
        6
    BeautifulSoap  
       2021-05-22 22:57:39 +08:00 via Android
    你好友黑名单数据难道是放在数据库之外的只能先获得好友 id 列表,然后 where in ?
    还是说表设计有问题?一般我觉得好友关系和黑名单信息是分开放在两个表里(或者单个表里有个字段标注是不是拉黑),想获得没有黑名单用户的信息的话,直接从好友那个表 join 不就行了,也用不到 in 的操作啊
    还有一点是你真的需要一次性搜出几千个用户数据吗?做数据分析还能理解,如果拿来做网页或给 app 提供数据,你根本用不着直接把所有数据都一次性搜出来吧
    512357301
        7
    512357301  
       2021-05-22 23:14:38 +08:00 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
       2021-05-22 23:42:22 +08:00
    比如现在要查询其他在线用户。
    那我首先获取到这个用户的黑名单 uidArr,
    然后拿着这个 uidArr 去 where not in 去剔除这些用户(对于这个用户黑名单可能有几千的数据)

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

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

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

    另外也可以试试 exists
    awanganddong
        12
    awanganddong  
    OP
       2021-05-23 19:25:36 +08:00
    单纯靠 mysql 已经解决不了这个问题了


    exists 和 union all 都用了 , 好不如原来的 where in 的性能
    uselessVisitor
        13
    uselessVisitor  
       2021-05-23 20:35:47 +08:00
    直接用代码实现会不会快一些捏?
    awanganddong
        14
    awanganddong  
    OP
       2021-05-24 21:46:03 +08:00
    想到一种思路

    where in ID 分段,然后我起多个线程或者多个携程并发请求。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2210 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:03 · PVG 00:03 · LAX 08:03 · JFK 11:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.