如何实现高效联表查询

8 篇文章 0 订阅
2 篇文章 0 订阅

本地缓存

缓存作为提高性能一种可选方式最先被考虑,其具有简单、易用、高效的特性。在结合Java8之后的新特性 Lambda 表达式,可以轻松实现类似 Join、Groupby、Sort 操作。

这个方式也是我首选的处理方式。其本质是将原本数据库处理压力转嫁到服务器内存中,鉴于现在绝大多数公司都是分布式架构,服务性能相比单体架构有明显的提升,反观,MySQL 在分布式时代常常成为性能的瓶颈,从而衍生出 TiDB 这类分布式数据库。

但缓存方式存在明显的短板—不适合大数据量操作,容易导致 Out Of Memory。但我有一个大胆,其实也称不上大胆想法,我们是不是可以实现 Spark SQL 一样在内存中构建表结构,处理表相关操作呢?如果有机会的话,再跟大家进行分享。

冗余

退而求其次,冗余也是常常被采用的方式,但其往往存在实时性和准确性的问题,因而只适合允许不精准和对变化宽容的场景。从本质来说,我认为冗余也是缓存的一种实现方式,如果这个问题,不局限于自身数据库去实现冗余,我们可以尝试使用 Redis 实现实时性的冗余,把所有服务都需要的用户手机号码信息放到 Redis 中,其他服务通过直接调用 Redis 获取数据,或者用户中心提供一系列查询 API 供其他业务线服务使用。而且 Github 上存在一个 rediSQL 开源项目,支持 Redis 数据通过 SQL 方式实现数据查询,现在已经孵化成为 zeeSQL,这样是不是可以更加 Think Big 了呢。

Join 查询

虽然本文已经使用大量的篇幅表明不愿意在数据库层面处理 Join 查询,但还是存在大量场景选用数据库 Join 操作才是比较简单高效的方式。因而,当不得不选择该种方式时,我们又有哪些提高查询性能的方式呢?

很多时候不是产品不够好,而是使用的人不会用。Join 查询也是一样,如果从实现原理了解,从根上对其有深入的了解,才能发挥其真正的作用。下面是我的一些摘记,与大家分享:

本文以 Left Join 作为示例说明,其他 Join 类似。

前提:

  1. 被 Join 表 关联字段需要存在索引
  2. 两表的关联字段需要编码格式一样,否则索引会失效

优化:

  1. 根据实际情况选择合适的Join算法(NLJ 和 BNL)
  2. 尽量使用 hash join(8.0.18 )
  3. 根据业务场景选择 Join 类型,尽可能选择 Join,而避免使用 Left Join 、Right Join、Full Join
  4. 关联条件存在 NULL 情况,在 where 语句中添加排除为空的条件
  5. 不使用子查询
  6. 结合实际业务场景选择合适 Join 方案

答疑:

Left Join 与 Join 原理区别

Join 以两张表中的数据量小的那张表作为基础表,依据关联条件,查询另一张表。Left Join 以左边那张表作为基础表,进行查询,往往左边那表是大表,所以 Join 查询要比 Left Join 性能好。

NLJ 和 BNL 原理

  • 嵌套循环连接 Nested-Loop Join(NLJ) 算法:

适用于关联的两个字段都为索引的情况下,首先会查询出全部驱动表的关联字段,然后一一去和被驱动表关联,直至全部关联完成。

  • 基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法:

如果关联字段不是索引或者有一个字段不是索引,MySQL则会采用此算法,和NLJ不同的是,BNL算法会多加一个join_buffer缓存块,关联时会把驱动表的部分数据放入到缓存块中,然后用被驱动表一一对比,直至查询完成。但是这个join_buffer缓存块是无序的,所以查询对比的次数会很多。

如何知晓当前查询属于哪种 Join 算法

至于一条SQL语句使用什么算法去做的关联操作,使用EXPLAIN命令可以查看,下面为嵌套循环连接算法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lhgt9JV0-1627483772136)(%E5%A6%82%E4%BD%95%E9%AB%98%E6%95%88%E5%AE%9E%E7%8E%B0%E8%81%94%E8%A1%A8%E6%9F%A5%E8%AF%A2/2020080400184089.png)]

基于块的嵌套循环连接 Block Nested-Loop Join(BNL)算法:

在这里插入图片描述

拓展阅读:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值