请教一个SQL优化的问题

问题描述

有一个member(会员表)和一个member_store(会员入会店铺表);member表存的是会员信息,member_store表存的是同一个会员在不同店铺的入会记录,有3个字段member_id(member表主键)、store_id(店铺id)、register_time(店铺注册时间);后台需要根据账号拥有的店铺权限来展示会员列表;所以现在的sql是这样的:

select m.* from member as m inner join member_store as ms on m.id=ms.member_id where ms.store_id in(1,2,3) group by m.id

一般一个后台账号会有十几个店铺的权限,当会员数量达到百万级后这条sql就会很慢;该加的索引都加了,因为必须要做数据权限的隔离,所以必须得关联member_store表;但是关联了之后就要group by来去重;就导致sql执行很慢。想问一下大家处理这种权限隔离除了用关联表来where in查询,还有没有其他处理方法

sql
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

谢谢大家提供了很多思路,领导已经准备换clickhouse了,此贴终结。

1年前 评论
讨论数量: 21

是需要显示用户信息列表是吧,

比如我有 10 个店铺,显示这10个店铺的所有用户


select  *  
from member 
where id in (
    select member_id 
    from member_store 
    where store_id in(1,2,3) 
    group by member_id 
    limit  0,10
)

试试这个看看行不行

1年前 评论
huchao399 (楼主) 1年前
kis龍 (作者) 1年前
陈先生 1年前

要不试试子查询 exists?虽然一般子查询比join慢,但是好像有文章提到过用子查询来优化是否存在的操作

1年前 评论
huchao399 (楼主) 1年前
小猪蹄子 (作者) 1年前

这相当于全表搞呀

1年前 评论
huchao399 (楼主) 1年前

member_store 的复合索引为 store_id,member_id

SELECT m.*
FROM member m
WHERE EXISTS (
   SELECT 1
   FROM member_store ms
   WHERE m.id = ms.member_id AND ms.store_id IN (1, 2, 3)
);

这样子效率怎么样

1年前 评论

最好贴出来你的 explain sql 语句,看看到底是哪里慢

1年前 评论

我们的也很慢, 用习惯了就好了 :sweat_smile:

1年前 评论

预先的数据结构和当前的需求不匹配的时候,不改原有设计的情况下,可以新建一张满足现有需要的表并维护。

1年前 评论

记录一下用户所属管理员的信息?这样可以直接查询。

1年前 评论

大家给了很多方案,有些在特定的情况下是可以解决慢的问题,但是不能满足现在的需求,领导说了,数据权限的隔离必须要做,那就必须要关联member_store表,关联这个表后做分页就要执行一次COUNT(DISTINCT m.id),来计算所有会员数量,真正慢的也是这条sql,会员列表展示是分页的,每页10条,查询速度也还行。目前也没有想到既能保证数据权限的隔离又不用关联表的方法。先这样吧,不管了......

1年前 评论
小猪蹄子 1年前

select * from member where m.id in( select distinct m.id from member as m inner join member_store as ms on m.id=ms.member_id where ms.store_id in(1,2,3))

这个怎么样?

1年前 评论
huchao399 (楼主) 1年前
kis龍 1年前
sanders

我觉得如果member.id是主键的话,换成子查询没必要 group by, member_store.store_id 加上索引试试。

select * from member where exists (select * from member_store where member_id=member.id and store_id in (1,2,3))

你可以把不同 sql 的 explain 执行结果发出来看一下,我们好帮你分析下索引的使用情况。

1年前 评论

谢谢大家提供了很多思路,领导已经准备换clickhouse了,此贴终结。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!