返回顶部
首页 > 资讯 > 数据库 >MySQL8.0 InnoDB并行执行
  • 803
分享到

MySQL8.0 InnoDB并行执行

MySQL8.0InnoDB并行执行 2015-09-29 14:09:24 803人浏览 猪猪侠
摘要

概述 Mysql经过多年的发展已然成为最流行的数据库,广泛用于互联网行业,并逐步向各个传统行业渗透。之所以流行,一方面是其优秀的高并发事务处理的能力,另一方面也得益于mysql丰富的生态。Mysql在处理OLTP场景下的短查询效果

MySQL8.0 InnoDB并行执行

概述

Mysql经过多年的发展已然成为最流行的数据库,广泛用于互联网行业,并逐步向各个传统行业渗透。之所以流行,一方面是其优秀的高并发事务处理的能力,另一方面也得益于mysql丰富的生态。Mysql在处理OLTP场景下的短查询效果很好,但对于复杂大查询则能力有限。最直接一点就是,对于一个SQL语句,MySQL最多只能使用一个CPU核来处理,在这种场景下无法发挥主机CPU多核的能力。MySQL没有停滞不前,一直在发展,新推出的8.0.14版本第一次引入了并行查询特性,使得check table和select count(*)类型的语句性能成倍提升。虽然目前使用场景还比较有限,但后续的发展值得期待。

使用方式

通过配置参数innodb_parallel_read_threads来设置并发线程数,就能开始并行扫描功能,默认这个值为4。我这里做一个简单的实验,通过sysbench导入2亿条数据,分别配置innodb_parallel_read_threads为1,2,4,8,16,32,64,测试并行执行的效果。测试语句为select count(*) from sbtest1;

横轴是配置并发线程数,纵轴是语句执行时间。从测试结果来看,整个并行表现还是不错的,扫描2亿条记录,从单线程的18s,下降到32线程的1s。后面并发开再多,由于数据量有限,多线程的管理消耗超过了并发带来的性能提升,不能再继续缩短SQL执行时间。

MySQL并行执行

实际上目前MySQL的并行执行还处于非常初级阶段,如下图所示,左边是之前MySQL串行处理单个SQL形态;中间的是目前MySQL版本提供的并行能力,InnoDB引擎并行扫描的形态;最右边的是未来MySQL要发展的形态,优化器根据系统负载和SQL生成并行计划,并将分区计划下发给执行器并行执行。并行执行不仅仅是并行扫描,还包括并行聚集,并行连接,并行分组,以及并行排序等。目前版本MySQL的上层的优化器以及执行器并没有配套的修改。因此,下文的讨论主要集中在InnoDB引擎如何实现并行扫描,主要包括分区,并行扫描,预读以及与执行器交互的适配器类。

分区

并行扫描的一个核心步骤就是分区,将扫描的数据划分成多份,让多个线程并行扫描。InnoDB引擎是索引组织表,数据以B+tree的形式存储在磁盘上,节点的单位是页面(block/page),同时缓冲池中会对热点页面进行缓存,并通过LRU算法进行淘汰。分区的逻辑就是,从根节点页面出发,逐层往下扫描,当判断某一层的分支数超过了配置的线程数,则停止拆分。在实现时,实际上总共会进行两次分区,第一次是按根节点页的分支数划分分区,每个分支的最左叶子节点的记录为左下界,并将这个记录记为相邻上一个分支的右上界。通过这种方式,将B+tree划分成若干子树,每个子树就是一个扫描分区。经过第一次分区后,可能出现分区数不能充分利用多核问题,比如配置了并行扫描线程为3,第一次分区后,产生了4个分区,那么前3个分区并行做完后,第4个分区至多只有一个线程扫描,最终效果就是不能充分利用多核资源。

二次分区

为了解决这个问题,8.0.17版本引入了二次分区,对于第4个分区,继续下探拆分,这样多个子分区又能并发扫描,InnoDB引擎并发扫描的最小粒度是页面级别。具体判断二次分区的逻辑是,一次分区后,若分区数大于线程数,则编号大于线程数的分区,需要继续进行二次分区;若分区数小于线程数且B+tree层次很深,则所有的分区都需要进行二次分区。相关代码如下:

split_point = 0;
if (ranges.size() > max_threads()) {
   //最后一批分区进行二次分区                                      
   split_point = (ranges.size() / max_threads()) * max_threads();          
 } else if (m_depth < SPLIT_THRESHOLD) {                                  
   
   split_point = max_threads();                                            
 } else {
   //如果B+tree的层次很深(层数大于或等于3,数据量很大),则所有分区都需要进行二次分区
 }

无论是一次分区,还是二次分区,分区边界的逻辑都一样,以每个分区的最左叶子节点的记录为左下界,并且将这个记录记为相邻上一个分支的右上界。这样确保分区足够多,粒度足够细,充分并行。下图展示了配置为3的并发线程,扫描进行二次分区的情况。

相关代码如下:

create_ranges(size_t depth, size_t level)
一次分区:
parallel_check_table
 add_scan
   partition(scan_range, level=0)  
     create_ranges(scan_range, depth=0, level=0)
   create_contexts(range, index >= split_point)
二次分区:                                                      
split()
 partition(scan_range, level=1)
   create_ranges(depth=0,level)

并行扫描

在一次分区后,将每个分区扫描任务放入到一个lock-free队列中,并行的worker线程从队列中获取任务,执行扫描任务,如果获取的任务带有split属性,这个时候worker会将任务进行二次拆分,并投入到队列中。这个过程主要包括两个核心接口,一个是工作线程接口,另外一个是遍历记录接口,前者从队列中获取任务并执行,并维护统计计数;后者根据可见性获取合适的记录,并通过上层注入的回调函数处理,比如计数等。

Parallel_reader::worker(size_t thread_id)

{

 1.从ctx-queue提取ctx任务

 2.根据ctx的split属性,确定是否需要进一步拆分分区(split())

 3.遍历分区所有记录(traverse())

 4.一个分区任务结束后,维护m_n_completed计数

 5.如果m_n_compeleted计数达到ctx数目,唤醒所有worker线程结束

 6.根据traverse接口,返回err信息。

}

Parallel_reader::Ctx::traverse()

{

 1.根据range设置pcursor

 2.找到btree,将游标定位到range的起始位置

 3.判断可见性(check_visibility)

 4.如果可见,根据回调函数计算(比如统计)

 5.向后遍历,若达到了页面的最后一条记录,启动预读机制(submit_read_ahead)

 6.超出范围后结束

}

同时在8.0.17版本还引入了预读机制,避免因为IO瓶颈导致并行效果不佳的问题。目前预读的线程数不能配置,在代码中硬编码为2个线程。每次预读的单位是一个簇(InnoDB文件通过段,簇,页三级结构管理,一个簇是一组连续的页),根据页面配置的大小,可能为1M或者2M。对于常见的16k页面配置,每次预读1M,也就是64个页面。worker线程在进行扫描时,会先判断相邻的下一个页面是否为簇的第一个页面,如果是,则发起预读任务。预读任务同样通过lock-free 队列缓存,worker线程是生产者,read-ahead-worker是消费者。由于所有分区页面没有重叠,因此预读任务也不会重复。

执行器交互(适配器)

实际上,MySQL已经封装了一个适配器类Parallel_reader_adapter来供上层使用,为后续的更丰富的并行执行做准备。首先这个类需要解决记录格式的问题,将引擎层扫描的记录转换成MySQL格式,这样做到上下层解耦,执行器不用感知引擎层格式,统一按MySQL格式处理。整个过程是一个流水线,通过一个buffer批量存储MySQL记录,worker线程不停的将记录从引擎层上读上来,同时有记录不停的被上层处理,通过buffer可以平衡读取和处理速度的差异,确保整个过程流动起来。缓存大小默认是2M,根据表的记录行长来确定buffer可以缓存多少个MySQL记录。核心流程主要在process_rows接口中,流程如下

process_rows

{

 1.将引擎记录转换成MySQL记录

 2.获取本线程的buffer信息(转换了多少mysql记录,发送了多少给上层)

 3.将MySQL记录填充进buffer,自增统计m_n_read

 4.调用回调函数处理(比如统计,聚合,排序等),自增统计m_n_send

}

对于调用者来说,需要设置表的元信息,以及注入处理记录回调函数,比如处理聚集,排序,分组的工作。回调函数通过设置m_init_fn,m_load_fn和m_end_fn来控制。

总结

MySQL8.0引入了并行查询虽然还比较初级,但已经让我们看到了MySQL并行查询的潜力,从实验中我们也看到了开启并行执行后,SQL语句执行充分发挥了多核能力,响应时间急剧下降。相信在不久的将来,8.0的会支持更多并行算子,包括并行聚集,并行连接,并行分组以及并行排序等。

参考文档

https://dev.mysql.com/worklog/task/?id=11720

Https://dev.mysql.com/worklog/task/?id=12978

https://yq.aliyun.com/articles/691516?utm_content=g_1000045831

http://mysql.taobao.org/monthly/2019/10/02/

https://www.percona.com/blog/2019/01/17/using-parallel-query-with-amazon-aurora-for-mysql/

您可能感兴趣的文档:

--结束END--

本文标题: MySQL8.0 InnoDB并行执行

本文链接: https://lsjlt.com/news/4521.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MySQL8.0 InnoDB并行执行
    概述 MySQL经过多年的发展已然成为最流行的数据库,广泛用于互联网行业,并逐步向各个传统行业渗透。之所以流行,一方面是其优秀的高并发事务处理的能力,另一方面也得益于MySQL丰富的生态。MySQL在处理OLTP场景下的短查询效果...
    99+
    2015-09-29
    MySQL8.0 InnoDB并行执行
  • MYSQL8.0 group by 无法执行问题
    查看:SELECT @@GLOBAL.sql_mode;  #将前面ONLY_FULL_GROUP_BY删除 set global sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_...
    99+
    2021-08-26
    MYSQL8.0 group by 无法执行问题
  • Python并行执行for循环
    简介 在介绍如何最简单地利用 python 实现并行前,我们先来看一个简单的代码。 words = ['apple', 'bananan', 'cake', 'dumpling'] for word in words:...
    99+
    2023-01-31
    Python
  • [python]map方法与并行执行
    文章也可参考: 我的个人博客 1. 内建方法map 内建map方法可以通过一个序列的方式来实现函数之间的映射, 并且串行执行。如: import time from datetime import datetime def ad...
    99+
    2023-01-31
    方法 python map
  • jQuery如何并行执行动画?
    这篇文章将为大家详细讲解有关jQuery如何并行执行动画?,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。jQuery 并行执行动画 jQuery 提供了强大的动画功能,允许开发者在网页元素上创建丰富的视觉...
    99+
    2024-04-02
  • MySQL innodb引擎的事务执行过程
    通过这篇文章可以了解到下面几个问题 ...
    99+
    2024-04-02
  • 怎么理解Oracle的并行执行
    这篇文章主要介绍“怎么理解Oracle的并行执行”,在日常操作中,相信很多人在怎么理解Oracle的并行执行问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Oracle...
    99+
    2024-04-02
  • Python并行化执行详细解析
    目录例子:N体问题普通计算方法效果图Python 并行化执行再举一个例子前言: 并行编程比程序编程困难,除非正常编程需要创建大量数据,计算耗时太长,物理行为模拟困难 例子:N体问题 ...
    99+
    2024-04-02
  • Appium Android?利用TestNG并行执行用例
      一、测试类*注1 package com.testerhome; import io.appium.java_client.android.AndroidDrive...
    99+
    2022-06-06
    testng appium Android
  • shell脚本怎么异步并行执行
    在shell脚本中,可以使用以下几种方式来实现异步并行执行:1. 后台执行:在命令后面加上`&`,可以将命令放到后台执行。例如:``...
    99+
    2023-09-22
    shell
  • PHP 函数并行执行优化策略
    php 中可以通过以下策略优化函数并行执行:使用多进程 (pcntl_fork)使用多线程 (pthread)使用 php 扩展(例如 parallel、amphp)通过应用这些策略,可...
    99+
    2024-04-12
    php 并行执行优化
  • oracle怎么并行执行存储过程
    在Oracle数据库中,存储过程可以通过使用并行执行来提高性能。以下是一些方法来实现并行执行存储过程: 使用并行提示:可以在存储...
    99+
    2024-04-09
    oracle
  • oracle sqlprofile 固定执行计划,并迁移执行计划
    sqlprofile固定执行计划 模拟10g 执行计划迁移至11g oracle数据库中,11g库用10g的执行计划,这里是把hint 全盘扫描的执行计划迁移  --1.准备阶段&nb...
    99+
    2024-04-02
  • Hive中并行执行是怎么工作的
    在Hive中,并行执行是通过将任务分解成多个子任务,并在集群中的多个节点上同时执行这些子任务来实现的。这样可以利用集群中的多个资源并...
    99+
    2024-03-14
    Hive
  • python 基于Appium控制多设备并行执行
    前言:     如何做到,控制多设备并行执行测试用例呢。 思路篇   我们去想下,我们可以获取参数的信息,和设备的信息,那么​我们也可以针对每台设备开启不一样的端口服务。...
    99+
    2024-04-02
  • Java并行执行任务的方案有哪些
    本篇内容介绍了“Java并行执行任务的方案有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!背景最近在排查生产环境问题,发现商品详情接口时...
    99+
    2023-06-25
  • PHP开发中如何优化并发执行和并行计算
    随着互联网应用的发展,对于程序的性能要求越来越高,特别是在并发执行和并行计算方面。在PHP开发中,如何优化并发执行和并行计算成为了一个重要的课题。本文将介绍一些优化技巧,并给出具体的代码示例。使用异步编程模型在PHP中,可以通过使用异步编程...
    99+
    2023-10-21
    并发执行优化 并行计算优化 PHP开发优化技巧
  • 怎么并发执行Linux命令
    这篇文章主要讲解了“怎么并发执行Linux命令”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么并发执行Linux命令”吧!串行是按照顺序一条接着一条的执行命令,与串行相对的是多条命令同时执...
    99+
    2023-06-15
  • python并发执行之多进程
        多进程顾名思义程序启动的时候运行多个进程,每个进程启动一条线程进行程序处理。 没启动一个进程就要单独划分一块内存资源。就像工厂的厂房。为了提高效率每多添加一条生产线就要单独再盖一个厂房。每个厂房相互是独立的。所以启动多进程是很消耗资...
    99+
    2023-01-31
    之多 进程 python
  • python 并发执行之多线程
        正常情况下,我们在启动一个程序的时候。这个程序会先启动一个进程,启动之后这个进程会拉起来一个线程。这个线程再去处理事务。也就是说真正干活的是线程,进程这玩意只负责向系统要内存,要资源但是进程自己是不干活的。默认情况下只有一个进程只会...
    99+
    2023-01-31
    之多 线程 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作