SQL优化:化解表关联的多对多join

本文通过一个实际案例,展示了如何通过优化SQL语句中的关联方式来显著提高查询效率,尤其是在处理多对多关系数据时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关系数据库的基本概念就是关系,对应到数据库软件中就是join,具体有:(1对1,1对多,多对多)。

在写sql时,经常会进行join,但是如果在join时没注意,关联条件是多对多,那么数据量就会成几何级数的增长,接下来又进行了group by,去除重复,真是吃力不讨好,曾经写过一个sql,运行需要7分钟,在修改之后,只需要10秒。。。


昨天写了一个存储过程,写好后发现非常慢,但是当前系统里的数据量就几十万条,数据量是比较小的。

代码如下:

declare @biz_date varchar(7)

set @biz_date = '2016-10'

select '达成率' kpi,
		4 as sort,
		v.emp_id,
		count(distinct v.store_id)*1.0/nullif(count(distinct m.store_id),0) v
FROM TB_CALL_PLAN v with(nolock)
inner  join TB_STORE m with(nolock)
	     on m.org_id = v.org_id and m.state = '1'
WHERE   v.business_date LIKE @BIZ_DATE+'%'
group by V.EMP_ID

这段代码运行时间是1分17秒,要计算某个人员的 达成率,逻辑也是很简单,其中的2个表是多对多的关系。

仔细想想慢可能是由于这种多对多的关系,一下子把数据集放大了好多倍,最后又通过group by 来去重 count(distinct store_id),所以就慢了。

于是修改了代码:

declare @biz_date varchar(7)

set @biz_date = '2016-10'

select '达成率' kpi,
		4 as sort,
		v.emp_id,
		count(distinct v.store_id)*1.0/nullif(c,0) v
FROM TB_CALL_PLAN v with(nolock)
inner  join 
(
	select m.org_id,
			count(*) as c
	from TB_STORE m with(nolock)
	where m.state = '1'
	group by m.org_id
)m
			on m.org_id = v.org_id
WHERE v.business_date LIKE @BIZ_DATE+'%'
group by V.EMP_ID,c
这段代码从表面看,好像是比最初的代码要复杂了,现在内部聚合tb_store的数据,然后再和外面的v表关联,但一个好处是对应关系变成了多对一的关系,也就是m的一个org_id对应多个v中的org_id,先把一个表的数据量通过group by缩小,然后再关联,这样关联数据就不会太多。

这么修改代码,运行时间降为0秒,实则是化繁为简。


<think>好的,我现在需要回答用户关于Redis和MySQL的共同点与区别的问题,包括功能对比、适用场景及相似之处。首先,我要回顾用户提供的站内引用内容,确保回答准确并引用相关部分。 用户给出的引用[1]提到Redis适合高性能缓存,学习成本最低,而MySQL复杂,需要学习SQL。引用[2]说明两者都通过端口监听处理请求,但存储方式不同:Redis内存存储,MySQL磁盘持久。引用[3]讨论了整合Redis主从集群和MySQL主从,提升缓存可用性。引用[4]涉及Kafka的副本机制,可能与当前问题无关,可以忽略。 用户之前的问题是关于反向代理和正向代理的区别,现在转向数据库对比,因此需要保持回答结构清晰,符合用户要求的层次结构。需要覆盖共同点、区别、功能对比、适用场景,并正确引用资料。 首先,共同点方面,根据引用[2],两者都通过端口监听接受请求,属于数据管理组件,并支持主从架构。接下来是核心区别,需要分数据模型、存储介质、查询语言、事务支持、性能等方面展开。功能对比要突出Redis的缓存和高速读写,MySQL的关系型数据管理。适用场景部分要分别列出Redis和MySQL的典型用例,如缓存、会话存储对应Redis,事务处理、复杂查询对应MySQL。最后,整合使用场景如引用[3]提到的Redis与MySQL主从集群结合使用,提升性能。 需要确保使用正确的LaTeX格式,如变量用$...$,公式用$$...$$。同时,添加相关问题,并检查引用标记是否正确。可能的问题包括如何选择两者,如何集成,性能优化方法等。 现在需要组织内容,确保逻辑连贯,信息准确,引用正确。可能需要注意避免技术错误,比如Redis支持的数据类型,MySQL的事务特性等。同时,保持语言简洁,结构清晰,符合用户要求的步骤解答。</think>### Redis 与 MySQL 的对比分析 #### 一、核心共同点 1. **数据管理组件** 两者均为数据存储与管理的关键技术,支持客户端通过**端口监听**接收请求并响应操作[^2]。 2. **主从架构支持** 均可通过主从复制(如引用[3]中的Redis主从集群与MySQL主从同步)实现**高可用性**与**读写分离**。 3. **持久能力** Redis支持内存快照(RDB)和日志追加(AOF)实现持久;MySQL通过事务日志(如InnoDB的redo log)保障数据一致性。 --- #### 二、核心区别 | **对比维度** | **Redis** | **MySQL** | |--------------------|------------------------------------------|------------------------------------------| | **数据模型** | 键值对(Key-Value),支持多种数据结构 | 关系型模型(表、行、列) | | **存储介质** | 内存为主(可持久) | 磁盘为主(内存缓存优化) | | **查询语言** | 无SQL,通过命令操作(如`GET key`) | 支持SQL(结构查询语言) | | **事务支持** | 简单事务(通过`MULTI/EXEC`) | ACID事务(复杂事务、锁机制) | | **性能特点** | 微秒级读写(内存操作) | 毫秒级响应(依赖索引与磁盘I/O优化) | | **适用场景** | 缓存、实时计数、会话存储 | 事务处理、复杂查询、持久业务数据 | --- #### 三、功能对比 1. **数据结构支持** - Redis:字符串(String)、列表(List)、哈希(Hash)、集合(Set)、有序集合(ZSet)、流(Stream)等[^2] ```bash > HSET user:1001 name "Alice" age 30 # 存储哈希类型数据 ``` - MySQL:仅支持二维表结构,通过外键关联实现复杂关系。 2. **扩展性与集群** - Redis:可通过分片(Sharding)或集群模式横向扩展,但需手动管理数据分布。 - MySQL:支持分库分表(如ShardingSphere),或通过主从复制提升读性能[^3]。 3. **一致性保障** - Redis:最终一致性(异步复制),牺牲部分一致性以换取高性能。 - MySQL:强一致性(通过事务日志与锁机制),适用于金融等高一致性场景。 --- #### 四、适用场景 | **场景类型** | **Redis** | **MySQL** | |--------------------|------------------------------------------|------------------------------------------| | **高频读/写** | 缓存热点数据(如商品详情页) | 低频写入、复杂查询(如订单统计报表) | | **实时性要求** | 实时排行榜、秒杀库存计数 | 用户账户余额更新、交易记录写入 | | **数据规模** | 适合小规模高频数据(受内存限制) | 支持海量数据存储(TB级) | | **业务复杂度** | 简单键值操作或特定数据结构需求 | 需要多表关联、事务回滚的业务逻辑 | --- #### 五、整合使用场景 1. **缓存加速** - 使用Redis缓存MySQL查询结果(如引用[3]),降低数据库压力。 - 流程示例: $$ \text{客户端} \xrightarrow{\text{读请求}} Redis \xrightarrow{\text{缓存未命中}} MySQL \xrightarrow{\text{回写}} Redis $$ 2. **异步任务队列** - Redis的List结构实现任务队列,MySQL持久任务最终状态。 - 例如:订单支付成功后,Redis队列触发库存扣减,MySQL记录订单状态。 3. **实时数据分析** - Redis存储实时指标(如UV/PV),MySQL存储明细数据供离线分析。 --- #### 六、选择建议 - **选Redis若**: - 需要微秒级响应(如缓存、会话存储) - 数据结构复杂(如地理位置、排行榜) - 容忍数据丢失风险(配置持久后可缓解)[^1] - **选MySQL若**: - 需强一致性事务(如银行转账) - 复杂查询需求(如JOIN操作、聚合函数) - 数据长期持久存储(如用户信息)[^2] --- ### 相关问题 1. Redis如何通过RDB和AOF实现数据持久? 2. 如何设计Redis与MySQL的双写一致性方案? 3. 在微服务架构中,Redis和MySQL分别承担什么角色? 4. MySQL的索引优化与Redis性能调优有何异同? --- 通过对比可见,Redis与MySQL在功能上互补,实际系统中常结合使用以兼顾性能与可靠性。例如,电商系统用Redis缓存商品库存,MySQL存储订单信息,两者协同提升整体效率[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值