精华内容
下载资源
问答
  • 关于MySQL8.0 InnoDB并行执行的详解发布时间:2020-03-27 11:06:15来源:亿速云阅读:690作者:小新今天小编给大家分享的是关于MySQL8.0 InnoDB并行执行的详解,很多人都不太了解,今天小编为了让大家更加了解MySQL...

    关于MySQL8.0 InnoDB并行执行的详解

    发布时间:2020-03-27 11:06:15

    来源:亿速云

    阅读:690

    作者:小新

    今天小编给大家分享的是关于MySQL8.0 InnoDB并行执行的详解,很多人都不太了解,今天小编为了让大家更加了解MySQL8.0,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。

    概述

    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;

    c122816503394b466d405d125fb10af3.png

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

    MySQL并行执行

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

    6169a17e16b9a407b14d2e8d08d88ad4.png

    分区

    并行扫描的一个核心步骤就是分区,将扫描的数据划分成多份,让多个线程并行扫描。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) {

    /* If the tree is not very deep then don't split. For smaller tables

    it is more expensive to split because we end up traversing more blocks*/

    split_point = max_threads();

    } else {

    //如果B+tree的层次很深(层数大于或等于3,数据量很大),则所有分区都需要进行二次分区

    }

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

    相关代码如下:

    17fcb05ae8e328e518b9571f47e5c7df.pngcreate_ranges(size_t depth, size_t level)

    一次分区:

    parallel_check_table

    add_scan

    partition(scan_range, level=0) /* start at root-page */

    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的会支持更多并行算子,包括并行聚集,并行连接,并行分组以及并行排序等。

    看完上文,你对关于MySQL8.0 InnoDB并行执行大概了解了吗?如果想了解更多,欢迎关注亿速云行业资讯频道哦

    展开全文
  • 摘要:在关系型数据库中,优化器是数据库的核心组件之一,由于一些列因素都会影响语句的执行,优化器综合权衡各个因素,在众多的执行计划中选择认为是最佳的执行计划。
    摘要:在关系型数据库中,优化器是数据库的核心组件之一,由于一些列因素都会影响语句的执行,优化器综合权衡各个因素,在众多的执行计划中选择认为是最佳的执行计划。

    本文分享自华为云社区《华为云GaussDB(for openGauss)专场直播第5期:SQL优化解读》,原文作者:心机胖。

    1.前言

    在关系型数据库中,优化器是数据库的核心组件之一,由于一些列因素都会影响语句的执行,优化器综合权衡各个因素,在众多的执行计划中选择认为是最佳的执行计划。随着大数据时代的到来,像电商、游戏、电信等行业都大规模的应用,单一数据库节点是难以应对数据规模的不断增长并确保性能的需要,业务面临“存不下、算得慢、算不准”的问题。而GaussDB(for openGauss)采用了可横向扩展的分布式架构,可以很好满足大规模海量数据的存储和计算的需求,其通过目标SQL执行计划的CBO成本,从目标SQL的诸多执行计划中选取成本值最小的执行路径为其执行计划,各执行路径的成本值是根据目标SQL中涉及到的表、索引、列等相关对象的统计信息计算出来的,实际反应执行目标SQL所要消耗的I/O、CPU和网络资源的一个估计值。

    • I/O资源:把表的数据从磁盘读入内存时所需代价
    • CPU资源:处理内存中表的数据所需的代价
    • 网络资源:需要DN间数据交互的分布式SQL,在实际执行时所需要的数据并不在本地DN中(需要从其他DN中取数据),便会将网络资源消耗折算成对等的I/O资源消耗再进行估算。

    本文结合第5场直播内容从分布式并行执行框架、分布式执行计划等方面进行介绍。

    2.分布式并行执行框架

    2.1 执行器:PIPELINE模型

    GaussDB(for openGauss)的执行器特点是:按照查询计划树从底往上执行,基于火山模型执行,即每个节点执行返回一行记录给父节点。

    火山模型的最大优点就是可以按需请求,每次只取出一条元组,在处理本条元组后,系统将会取出下一条满足条件的元组,直到取出所有满足条件的元组为止。从这种方式的运行机制可以看出,其每次执行时对于系统资源的需求都非常小。

    2.2 高性能分布式查询引擎

    GaussDB(for openGauss)充分利用当前多核特点,通过多线程并发执行,提高系统吞吐量。众所周知,在传统的分布式 MPP 数据库中,因数据的重分布,也就是数据shuffle的代价非常昂贵,从而限制了用户使用场景范围。

    GaussDB(for openGauss)能充分利用当前多核特点,采用并行执行机制,在SQL执行优化方面有多年的沉淀,并提供了三种stream流(广播流、聚合流和重分布流)来降低数据在DN节点间的流动,突破了传统分布式 MPP 数据库因为数据shuffle代价高昂带来的用户使用场景限制,即使是复杂的SQL、事务分析混合(HTAP)场景也能得到最佳执行。

    GaussDB(for openGauss)的大致执行过程:

    • 业务应用下发SQL给Coordinator ,SQL可以包含对数据的CRUD操作;
    • Coordinator利用数据库的优化器生成执行计划,每个DN会按照执行计划的要求去处理数据;
    • 数据基于一致性Hash算法分布在每个DN,因此DN在处理数据的过程中,可能需要从其他DN获取数据,GaussDB提供三种stream流(广播流、聚合流和重分布流)实现数据在DN间的流动,使得join无需抽取到CN执行;
    • DN将结果集返回给Coordinate进行汇总;
    • Coordinator将汇总后的结果返回给业务应用。

    3.分布式执行计划

    CN根据表的分布列信息和关联列信息进行判定,SQL语句是否可以直接在各个DN上执行而且不需要数据交流,如果是,CN采用LIGHT_QUERY或FQS_QUERY流程,保持了事不关己的态度,你发给我什么我就下发什么,直接将整个query命令下发给DN执行,执行完成后直接输出;如果需要在各个DN之间进行数据交互,则会选择使用stream算子;如果发现无法使用stream算子时,就回到了原始的PGXC流程。

    3.1 LIGHT_QUERY

    - 场景:语句可以直接在一个DN执行(单shard语句,点查场景)。

    - 原理:CN直接下发语句QPBE报文到对应DN,这样的做的好处是,执行效率高,线性扩展比好。

    create table t1 ( col1 int, col2 varchar ) distribute by hash(col1);
    create table t2 ( col1 int, col2 varchar ) distribute by hash(col1);

    3.2 FQS_QUERY

    - 场景:当语句可以完全下推到多个DN上执行,且DN之间不需要数据交互时。

    - 原理:CN不通过优化器,直接生成RemoteQuery计划,走执行器逻辑下发到DN,各DN根据下推语句生成执行计划并进行执行,执行结果在CN上进行汇总。

    create table t1 ( col1 int, col2 varchar ) distribute by hash(col1);
    create table t2 ( col1 int, col2 varchar ) distribute by hash(col1);

    LIGHT_QUERY和FQS_QUERY的最大异同点在于,虽然CN都是经过判定后直接把收到的query下发给DN进行处理,但是LIGHT_QUERY只涉及到单DN进行操作,而FQS_QUERY涉及到多个DN分别进行操作,它们都不会涉及到DN间的数据交互。

    3.3 STREAM GATHER

    - 场景:需要各DN之间进行数据交互。

    - 原理:CN根据原语句通过优化器生成带stream算子的执行计划,下发给DN进行执行,DN执行过程中存在数据交互(stream节点),stream算子在DN之间建立连接进行数据交互,CN汇总执行结果并承担大部分计算。

    create table t1 ( col1 int, col2 varchar ) distribute by hash(col1);
    create table t2 ( col1 int, col2 varchar ) distribute by hash(col2);

    3.4 STREAM REDISTRIBUTE

    - 场景:需要各DN之间进行数据交互。

    - 原理:CN根据原语句通过优化器生成带stream算子的执行计划,下发给DN进行执行,各DN执行过程中存在数据交互(stream节点),stream算子在DN之间建立连接进行数据交互,CN汇总执行结果并承担大部分计算。

    create table t1 ( col1 int, col2 varchar ) distribute by hash(col1);
    create table t2 ( col1 int, col2 varchar ) distribute by hash(col2);

    3.5 STREAM BROADCAST

    - 场景:需要各DN之间进行数据交互。

    - 原理:CN根据原语句通过优化器生成带stream算子的执行计划,下发给DN进行执行,各DN执行过程中存在数据交互(stream节点),stream算子在DN之间建立连接进行数据交互,CN汇总执行结果并承担大部分计算。

    create table t1 ( col1 int, col2 varchar ) distribute by hash(col1);
    create table t2 ( col1 int, col2 varchar ) distribute by hash(col2);

    使用REDISTRIBUTE算子时,数据进行重分布可以充分利用多个节点的算力,而BROADCAST算子主要用于stream的子计划产生的数据量较少的情况,此时BROADCAST的代价较少。

    3.6 PGXC

    - 场景:不能满足前面处理方式的极端场景,性能非常差。

    - 原理:CN通过优化器把原语句中的部分语句生成RemoteQuery计划,把每个RemoteQuery下发到DN,DN执行后把中间结果数据发送给CN,CN收集后进行剩余执行计划的执行计算,CN承担了大部分计算。

    总结

    综上所述,GaussDB(for openGauss)作为自主研发的新一代金融级分布式关系型数据库,采用可横向扩展的分布式架构,通过SQL优化器生成分布式算子以及分布式执行计划,提供了三种stream流(广播流、聚合流和重分布流)来降低数据在DN节点间的流动;执行引擎是一个分布式并行执行框架,支持节点间并行和节点内并行能力,充分利用当前多核特点,通过并发执行,提高系统吞吐量,具备大数据下高性能查询能力。

     Ps:更多精彩内容,请点击回播链接进行观看:https://bbs.huaweicloud.com/live/cloud_live/202107061900.html 

    点击关注,第一时间了解华为云新鲜技术~

    展开全文
  • MySQL8.0 InnoDB并行执行

    2021-01-19 21:15:27
    MySQL并行执行 实际上目前MySQL的并行执行还处于非常初级阶段,如下图所示,左边是之前MySQL串行处理单个SQL形态;中间的是目前MySQL版本提供的并行能力,InnoDB引擎并行扫描的形态;最右边的是未来MySQL要发展的...

    概述

    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;

    2271c211adb160417cd5c204ca71308b.png

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

    MySQL并行执行

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

    38209e4424bf8dc2cd02a55e4f8096a1.png

    分区

    并行扫描的一个核心步骤就是分区,将扫描的数据划分成多份,让多个线程并行扫描。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

    it is more expensive to split because we end up traversing more blocks*/split_point=max_threads();

    }else{//如果B+tree的层次很深(层数大于或等于3,数据量很大),则所有分区都需要进行二次分区

    }

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

    9724ca2357e0cce35a0825471bfc5497.png

    相关代码如下:

    create_ranges(size_t depth, size_t level)

    一次分区:

    parallel_check_table

    add_scan

    partition(scan_range, level=0) /*start at root-page*/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的会支持更多并行算子,包括并行聚集,并行连接,并行分组以及并行排序等。

    参考文档

    展开全文
  • GNU Parallel是用于执行此操作的工具。顾名思义,GNU Parallel可用于并行构建和运行命令。您可以使用不同的参数运行同一命令,无论它们是文件名,用户名,主机名还是从文件读取的行。GNU Parallel提供了对许多最常见...

    在Bash中没有内置并行运行命令的方法。GNU Parallel是用于执行此操作的工具。

    顾名思义,GNU Parallel可用于并行构建和运行命令。您可以使用不同的参数运行同一命令,无论它们是文件名,用户名,主机名还是从文件读取的行。GNU Parallel提供了对许多最常见操作(输入行,输入行的各个部分,指定输入源的不同方式等)的简写引用。并行可以从xargs其输入源替换命令或将命令提供给多个不同的Bash实例。

    有时候你执行的命令也许不需要等待上一个命令运行完成之后再运行下一个,因此你可能会想到让这些命令并行运行,减少你的任务执行时间,或者加快项目构建速度

    在本教程中,简单介绍Parallel命令的常见用法和解释

    安装

    从源码中构建,适用于任何操作系统wget http://ftp.gnu.org/gnu/parallel/parallel-latest.tar.bz2

    sudo tar xjf parallel-latest.tar.bz2

    cd parallel-latest/

    sudo ./configure && make

    sudo make install

    在ubuntu/debian/Linux mint等发行版sudo apt-get install parallelubuntu/debian

    使用parallel并行执行多个命令

    使用parallel非常简单,只需要在parallel后面连接多个命令,并且使用空格分开,下面命令中将会并行执行ls,echo foo,pwd命令parallel -vk ::: ls 'echo foo' pwd

    从标准输入读取parallel命令参数

    在某些情况会使用标准输入读取命令参数,然后传递给parallel执行任务,下面是一个简单的示例echo 1,2 | parallel -d, echo {}

    在这个示例parallel通过管道从标准输入读取命令参数,然后将参数传递给后面的echo命令,大括号{}这里将会填充从标准输入中的参数,-d,表示使用逗号,作为参数分隔符

    命令输出如下所示Academic tradition requires you to cite works you base your article on.

    When using programs that use GNU Parallel to process data for publication

    please cite:

    O. Tange (2011): GNU Parallel - The Command-Line Power Tool,

    ;login: The USENIX Magazine, February 2011:42-47.

    This helps funding further development; AND IT WON'T COST YOU A CENT.

    If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

    To silence this citation notice: run 'parallel --citation'.

    1

    2

    还有常见的用法就是parallel后面接着需要执行的命令,如下所示parallel echo ::: A B C

    这将并行打印ABC,输出如下Academic tradition requires you to cite works you base your article on.

    When using programs that use GNU Parallel to process data for publication

    please cite:

    O. Tange (2011): GNU Parallel - The Command-Line Power Tool,

    ;login: The USENIX Magazine, February 2011:42-47.

    This helps funding further development; AND IT WON'T COST YOU A CENT.

    If you pay 10000 EUR you should feel free to use GNU Parallel without citing.

    To silence this citation notice: run 'parallel --citation'.

    A

    B

    C

    使用parallel代替 xargs

    例如,使用gzip替换xargs压缩当前目录及其子目录中的所有html文件:find . -type f -name '*.html' -print | parallel gzip

    如果您需要保护特殊字符(例如文件名中的换行符),请使用find的 -print0 选项

    当文件数量太大而无法通过一次mv调用处理时,可以使用Parallel从当前目录移动文件:find . -depth 1 \! -name '.*' -print0 | parallel -0 -X mv {} destdir

    如您所见,{}被替换为从标准输入读取的每一行。虽然使用在大多数情况下都可以使用,但不足以处理所有文件名。如果需要在文件名中包含特殊字符,则可以使用find . -depth 1 \! -name '.*' -print0 | parallel -0 mv {} destdir

    如上所述。

    这将运行mv与当前目录中的文件一样多的命令。您可以通过添加-X 选项find . -depth 1 \! -name '.*' -print0 | parallel -0 -X mv {} destdir

    GNU Parallel可以替换某些从文件读取的行上使用的常见用法(在这种情况下,文件名每行列出一个):while IFS= read -r x; do

    do-something1 "$x" "config-$x"

    do-something2 < "$x"

    done < file | process-output

    具有更紧凑的语法,让人联想到lambdas:cat list | parallel "do-something1 {} config-{} ; do-something2 < {}" |

    process-output

    Parallel提供了一种内置的机制来删除文件名的扩展名,这使其可以进行批处理文件转换或重命名:ls *.gz | parallel -j+0 "zcat {} | bzip2 >{.}.bz2 && rm {}"

    这将使用bzip2重新压缩当前目录中所有以.gz结尾的文件,每个CPU核心(-j + 0)并行运行一个作业。(在这里我们为简洁起见使用ls;面对包含意外字符的文件名,使用上面的find方法更健壮。)并行可以从命令行获取参数;以上也可以写成parallel "zcat {} | bzip2 >{.}.bz2 && rm {}" ::: *.gz

    如何保证parallel输出的顺序

    如果命令生成输出,则可能要在输出中保留输入顺序。例如,以下命令{

    echo myfreax.com ;

    echo debian.org ;

    echo freenetproject.org ;

    } | parallel traceroute

    将作为输出显示首先完成的traceroute的调用。添加-k 选项{

    echo myfreax.com ;

    echo debian.org ;

    echo freenetproject.org ;

    } | parallel -k traceroute

    将确保traceroute myfreax.com首先显示的输出。

    如何并行执行文件中的命令

    最后,可以使用Parallel并行运行一系列Shell命令,比如‘cat file | bash’。在文件创建一系列shell命令以对其进行操作并不少见。并行可以加快速度。比如你有一个文件file, 包含一系列shell命令,每行一个,如下所示ls

    touch

    datefileparallel -j 10 < file

    shell将会评估并执行命令,并一次执行十个命令,直到完成为止,有关完整的描述,请参考GNU Parallel文档。

    展开全文
  • 肯定不能直接跑上面SQL,其一,这是一个大事务,会导致主从延迟,其次,SQL没有where过滤条件,会把整个表锁住 对表根据主键切片之后,可以将数据分为多份,然后开多个窗口并行执行,这样就能加快UPDATE执行速度 ...
  • 1.Promise.all 并行执行promise getA和getB并行执行,然后输出结果。如果有一个错误,就抛出错误 /** * 每一个promise都必须返回resolve结果才正确 * 每一个promise都不处理错误 */ const getA = new Promise(...
  • java并行执行多个任务

    千次阅读 2021-02-26 15:16:37
    java并行执行多个任务:最近做项目中,有个任务需要实现并发编程,个人参考了下网上的实现,自己实现了下并发方法,并且增加了简单的说明,希望的有需要的朋友有些帮助。import java.util.UUID;import java.util....
  • 从reduce的文档中:标识值必须是累加器功能的标识。 这意味着对于所有t,accumulator.apply(identity,t)等于t。在您的情况下,这是不正确的-“”和“ a”创建了“ / a”。我已经提取了累加器功能并添加了打印输出以...
  • 我的应用程序中的一种Spring服务方法向另外两个微服务发出请求.我想使用Hystrix做出这些请求以使其具有容错能力,并且我想并行运行它们....是否可以使用Observable功能并行执行Hystrix命令?在伪代码中,所需的解决...
  • 最近在排查生产环境问题,发现商品详情接口时不时会报RPC调用超时,检查代码发现接口里面查询活动耗时比较长,都是串行执行的,仔细查看发现完全可以改成并行执行,缩短接口查询耗时。 比如我们的商品详情接口,...
  • Spring并行执行方法

    2021-03-03 11:34:38
    小编典典对于您使用AsyncResult的原因(以及哪个实现…ejb?),我有些困惑。如果我没记错的话,它就不会那样工作,因为(据我所知)...如果是这样,则需要在执行程序中实际运行这些Future,然后等待调用future.get...
  • 目前流行的并行运行方法1.1 官方parallel参数1.2 个人开发者写的插件1.3 基于 CI 平台的2. GitLab CI Parallel2.1 介绍2.2 使用方法3. 根据 CI_NODE_INDEX 生成测试目录3.1 切分用例的不同方向3.2 实现效果3.3 源码...
  • 我正在寻找一个运行一系列命令的工具,比如现有的工具: parallel -h parallel [OPTIONS] command... 编辑:为了强调,我想在每个主机上运行不同的命令 – 通常使用不同的参数运行相同的程序,如上面的第一个并行用法示例.
  • } } 串行递归转位并行递归 public<T> void seqRecursive(){ for(Node<T> n: nodes){ results.add(n.compute()); seqRecursive(n.getChildren(),results); } } public<T> void parallelRecursive(final Executor ...
  • 【参考】并发与并行的区别是什么? —>...并发(concurrent)【美/kənˈkɜːrənt/】: 无论上一个开始执行的任务是否完成,当前任务都...并行(parallel)【美/ˈpærəlel/】: 有多个任务执行单元,从物理上就可
  • 小计一下学习的内容 @Component @EnableAsync public class AsnycThreadPoolConfig { @Bean("asyncThreadPool") public ThreadPoolExecutor asyncThreadPool () { return new ThreadPoolExecutor(2, ...
  • 如果你在Oracle 数据库的并行执行的实际操作中,你对Oracle 数据库的并行执行有不解之处时,你可以通过以下的文章对其的实际应用与功能有所了解,以下是文章的具体介绍,望你浏览完以下的内容会有所收获。...
  • 将自动化脚本发布到多个物理机或者虚拟机(跨平台、跨浏览器)上执行,通过一个中心节点来控制多个设备,也就是在中心节点(hub)上运行测试,在其它节点(node)上执行,实现selenium的并行执行。除了可以在多个...
  • I have a multithreaded application that periodically fetches the whole content of the MySQL table (with SELECT * FROM query)The application is written in python, uses threading module to multithreadi....
  • 在shell中可以通过使用【{需要并行执行的部分}$】这样的模式实现对某一段脚本进行并行处理。 下面先来看一下一个单线程的程序。 #!/bin/bash cat test.txt | while line do echo "${line}" sleep 5 done 上面这...
  • 命令并行执行的实现

    2021-10-30 15:32:15
    我们日常在系统执行命令时都是顺序执行,效率比较低,如果命令并行执行的话,肯定会大大提高我们的工作效率,将来我们也可以利用并行执行这个技术来访问一些比较消耗资源的脚本,比如:扫描网段,当然命令并行执行的...
  • 文章目录为什么要有线程如何创建线程线程的...如果一个任务是可以拆解的,前后相关性没有很大关联,就可以并行执行。 比如有个开发任务,要开发200个页面,可以拆分成10个任务,每个任务负责10个页面,并行开发,完成之
  • 通用的多函数同时执行模板,所有函数执行结果均不为error时表示执行成功 带上上下文Context做超时处理 代码 func FuncsParallelRunningWithContext(functions []func() error, ctx context.Context) (err error) { ...
  • #!/usr/bin/python# -*- coding: utf-8 -*-import sysimport subprocessimport os'''argv[1] 日期argv[2] 本地rsync路径【暂时没用】argv[3] 远程rsync ipargv[4] 任务列表地址'''class RsyncTask:def __init__ ...
  • SpringBoot中定时任务默认是串行执行 如何设置并行SpringBoot项目中,定时任务默认是串行执行的,不论启动多少任务,都是一个执行完成,再执行下一个. 如何设置并行呢? @EnableAsync 和@Async 这两个注解来实现 ,具体...
  • 背景介绍有时候我们需要执行一批相似的任务,并且要求这些任务能够并行执行。通常,我们的需求会分为两种情况:并行执行一批任务,等待耗时最长的任务完成之后,再处理所有任务的结果。并行执行一批任务,依次处理...
  • 第四章 数据并行执行模型 《大规模并行处理器编程实战》学习,其他章节关注专栏 CUDA C 线程组成线程块,线程块组成线程网格,线程网格就是kernel。一个kernel中的所有线程都执行相同的代码,区别在于不同的线程...
  • 并行执行模块总体上可以划分为计划生成和计划执行两个阶段。 并行计划生成 OceanBase 首先总是会生成一个本地串行计划,然后根据计划中每个算子的分区信息决定是否将其转化成一个并行计划。例如,在 select 语句的...
  • 1、不使用并发执行用例方式 如下有十个用例,每个用例中等待5秒,使用pytest顺序执行 import time def test_testcase_01(): time.sleep(5) def test_testcase_02(): time.sleep(5) def test_testcase_03(): ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 534,010
精华内容 213,604
关键字:

并行执行