问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

MySQL分区表IN查询性能优化分析

创作时间:
作者:
@小白创作中心

MySQL分区表IN查询性能优化分析

引用
CSDN
1.
https://m.blog.csdn.net/weixin_44985880/article/details/145477513

在对大数据表进行分区处理时,通过IN条件进行数据查询的SQL性能可能会变差。本文将分析这一现象的原因,并提供相应的解决方案。

背景

当涉及到分区表时,查询优化的考量就会变得更加复杂。分区表将数据分散存储在多个物理存储区域中,通常基于某个字段(如 id、日期等)进行分区。分区的目的是提高查询性能,尤其是在涉及到大数据量时。

假设我们的表是基于某个字段(例如 id)进行分区,通常会使用范围分区(RANGE)或列表分区(LIST)等方式对数据进行分区。分区优化和查询优化的目标是尽可能少地访问不相关的分区。

示例表结构

student表为例,该表包含的主要字段如下:

其中该表的分区字段是gradeId,属于同一个年级的学生信息将会分到同一个区内。

查询性能对比

第一种查询:仅通过主键ID进行IN查询

SELECT * FROM table_name WHERE id IN (list_of_ids);

执行计划分析:

分区表的查询优化首先会考虑“分区裁剪”。如果查询条件中的 id 值能够帮助 MySQL 确定哪些分区需要扫描,MySQL 会只扫描这些分区。假设 id 是分区键,MySQL 会使用索引来快速定位到这些分区。

性能考虑:

分区裁剪优化:如果查询中的 id 值能够快速确定查询的分区,那么 MySQL 会避免扫描不相关的分区。这样,虽然使用的是 ref 类型,但仍然能减少扫描的数据量,特别是在表有很多分区时。

但是对于student表而言,分区字段是gradeId而并非主键ID,所以单通过主键ID的条件集合并不能确定将要在哪些分区表进行数据查询。

这个时候有小伙伴可能会有疑问,主键ID一定是有主键索引,对于已经分区的表,如果 id 列有索引,MySQL 会尽量通过索引来查找匹配的记录,减少全表扫描的开销。那么通过主键索引就可以唯一确定数据了,查询速度应该最快才对,

但是如果放在未进行分区的数据表中来看,通过主键ID的查询的确是最快的,因为所有的数据都是在一张表中,直接通过索引定位即可,但是别忘了此时student表是已经进行了分区的, 因此对于这种条件查询,mysql会将所有的分区表的数据进行聚合之后再使用主键索引进行查询,此时的性能就不一定最优了!

第二种查询:IN查询+分区键限制

SELECT * FROM table_name WHERE id IN (list_of_ids) AND gradeId = 'specific_value';

执行计划分析:

与第一种查询相似,分区裁剪仍然是优化的关键。如果 id 是分区键,MySQL 会根据 id 值来决定哪些分区需要访问。如果 gradeId 是索引列,则 MySQL 会根据 id 和 gradeId 的组合来进一步过滤查询范围。

性能考虑:

分区裁剪与精确匹配:第二种查询添加了 gradeId 条件,这使得查询更加精确。当 gradeId 作为额外的筛选条件时,尤其是它本身是索引列(唯一索引),MySQL 可以更快速地定位到唯一记录,并且可能通过复合索引来加速查询。
减少扫描的分区:gradeId作为分区键,MySQL 会根据分区键 gradeid 进行裁剪后,再通过索引对 主键Id 进行精确匹配。通过减少访问不相关的分区,并且优化 id 和 gradeId 的匹配条件,查询会比单纯依赖 id 查询更高效。

为什么第二种查询性能更优?

主要原因:

更精确的过滤: 第二种查询中,gradeId 作为分区键和额外的筛选条件,不仅可以帮助mysql裁剪到具体的分区表,而且还可以进一步减少扫描的行数。特别是当 gradeId和主键ID有联合索引时,MySQL可以在每个分区内精确地定位符合条件的记录,避免不必要的数据扫描。

分区裁剪与多索引的结合: 第二种查询利用了 gradeId 的分区裁剪和对 主键ID 的索引,通常能减少不必要的分区扫描和记录扫描,从而提高查询性能。

总结

第一种查询:IN 查询先将分区数据全部聚合,然后使用索引查找匹配记录。由于 IN 查询可能返回多个结果,因此通常使用 ref 类型。

第二种查询:IN 查询与 gradeId 限制条件组合,MySQL 会利用gradeId 分区裁剪和对 主键ID的精确匹配, 尤其是当 gradeId 和主键ID具有联合索引时 ,通常使用 eq_ref 类型。eq_ref 类型的查询比 ref 类型的查询通常更高效,因为它表示每次查找只会返回一条记录。

对于已经分区的表,第二种查询通常会比第一种查询更高效,因为它减少了扫描的分区和记录,并利用了索引和精确匹配来加速查询过程。

因此得到一个最终结论,对于已经分区的表,在进行数据查询时,要尽可能将分区字段作为查询条件之一,并将分区键和主键ID建立联合索引,以提高查询性能。这个结论对于条件删除和条件修改同样适用,

后面我们将分享一下mybatisPlus在处理分区表数据的批量编辑时,如何自定义批量编辑方法,从而通过分区键和主键ID快速修改数据。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号