倘若没有并行查询技术,一个串行执行的查询语句只能利用CPU或者磁盘设备中的一个,而不能利用整个计算机的处理能力。并行查询技术的出现,使得单个SQL语句能利用多个CPU和磁盘设备的处理能力。其优势在于可以通过多个线程来处理查询任务,从而提高查询的效率。
达梦数据库为具有多个CPU的数据库服务器提供并行查询的功能,以优化查询任务的性能。数据库服务器只有具有多个CPU,才能使用并行执行查询操作,来提高查询任务的速度。
达梦数据库通过三个步骤来完成并行查询:首先,确定并行任务数;其次,确定并行工作线程数;最后,执行查询。并行查询相关参数见下表:
参数名 缺省值 属性 说明
MAX_PARALLEL_DEGREE 1 动态,会话级 用来设置默认并行任务个数。取值范围:1~128。缺省值1,表示无并行任务。当PARALLEL_POLICY值为1时该参数值才有效。
parallel_policy 0 静态 用来设置并行策略。取值范围:0、1和2,缺省为0。其中,0表示不支持并行;1表示自动并行模式;2表示手动并行模式。
PARALLEL_THRD_NUM 10 静态 用来设置并行工作线程个数。取值范围:1~1024。
当开启自动并行(PARALLEL_POLICY=1)时,参数MAX_PARALLEL_DEGREE生效,控制并行查询最多使用的线程数。MAX_PARALLEL_DEGREE缺省值为1,表示不并行。此时若指定参数对应的HINT “PARALLEL”,则使用HINT值;
当开启手动并行(PARALLEL_POLICY=2)时,参数MAX_PARALLEL_DEGREE失效,用户需要在语句中使用此参数对应的HINT “PARALLEL”指定语句的并行度,否则不并行。
1.在INI参数中设置默认值
INI参数MAX_PARALLEL_DEGREE设置最大并行任务个数。取值范围:1~128。缺省值1,表示无并行任务,此参数仅在PARALLEL_POLICY值为1时才有效。
例如,在INI参数中将MAX_PARALLEL_DEGREE设置为3的格式如下:
MAX_PARALLEL_DEGREE 3
先查看max_parallel_degree的缺省值
SQL> select sf_get_para_value(1,'MAX_PARALLEL_DEGREE');
LINEID SF_GET_PARA_VALUE(1,'MAX_PARALLEL_DEGREE')
---------- ------------------------------------------
1 1
used time: 150.207(ms). Execute id is 197.
下面的查询将查看dm.ini文件中设置的max_parallel_degree参数值
SQL> select * from v$dm_ini where para_name='MAX_PARALLEL_DEGREE';
LINEID PARA_NAME PARA_VALUE MIN_VALUE MAX_VALUE MPP_CHK SESS_VALUE FILE_VALUE DESCRIPTION PARA_TYPE
---------- ------------------- ---------- --------- --------- ------- ---------- ---------- -------------------------------- ---------
1 MAX_PARALLEL_DEGREE 1 1 128 N 1 1 Maximum degree of parallel query SESSION
used time: 50.228(ms). Execute id is 198.
下面的查询将查看内存中的max_parallel_degree参数值
SQL> select * from v$parameter where name='MAX_PARALLEL_DEGREE';
LINEID ID NAME TYPE VALUE SYS_VALUE FILE_VALUE DESCRIPTION
---------- ----------- ------------------- ------- ----- --------- ---------- --------------------------------
1 274 MAX_PARALLEL_DEGREE SESSION 1 1 1 Maximum degree of parallel query
used time: 7.440(ms). Execute id is 199.
现在执行下面的命令来同时修改内存与dm.ini文件中的max_parallel_degree参数为3
SQL> call sp_set_para_value(1,'MAX_PARALLEL_DEGREE',3);
DMSQL executed successfully
used time: 7.183(ms). Execute id is 200.
执行下面的查询可以看到max_parallel_degree参数修改为3了
SQL> select sf_get_para_value(1,'MAX_PARALLEL_DEGREE');
LINEID SF_GET_PARA_VALUE(1,'MAX_PARALLEL_DEGREE')
---------- ------------------------------------------
1 3
used time: 5.544(ms). Execute id is 201.
从查询返回的sess_value与file_value都为3可以确定max_parallel_degree在dm.ini文件中已经被修改了
SQL> select * from v$dm_ini where para_name='MAX_PARALLEL_DEGREE';
LINEID PARA_NAME PARA_VALUE MIN_VALUE MAX_VALUE MPP_CHK SESS_VALUE FILE_VALUE DESCRIPTION PARA_TYPE
---------- ------------------- ---------- --------- --------- ------- ---------- ---------- -------------------------------- ---------
1 MAX_PARALLEL_DEGREE 3 1 128 N 3 3 Maximum degree of parallel query SESSION
used time: 6.910(ms). Execute id is 202.
从查询返回的sys_value为3可以在内存中max_parallel_degree也已经被修改了。
SQL> select * from v$parameter where name='MAX_PARALLEL_DEGREE';
LINEID ID NAME TYPE VALUE SYS_VALUE FILE_VALUE DESCRIPTION
---------- ----------- ------------------- ------- ----- --------- ---------- --------------------------------
1 274 MAX_PARALLEL_DEGREE SESSION 3 3 3 Maximum degree of parallel query
used time: 6.335(ms). Execute id is 203.
然后,使用一般的SQL语句查询即可执行并行查询,不需要使用HINT。如:
SQL> explain SELECT * FROM SYSOBJECTS;
1 #NSET2: [0, 1694, 396]
2 #LOCAL COLLECT: [0, 1694, 396]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) for_sync(FALSE)
3 #PRJT2: [0, 1694, 396]; exp_num(17), is_atom(FALSE)
4 #CSCN2: [0, 1694, 396]; SYSINDEXSYSOBJECTS(SYSOBJECTS as SYSOBJECTS)
used time: 0.951(ms). Execute id is 0.
执行计划中的LOCAL COLLECT 代表:本地并行下数据收集处理,代替LOCAL GATHER。
2.在SQL语句中使用“PARALLEL”关键字特别指定
当PARALLEL_POLICY=2时,需要在SQL语句中通过“PARALLEL”HINT指定并行度,否则不并行。若PARALLEL_POLICY=1,则SQL语句中使用的“PARALLEL”HINT总是优先于MAX_PARALLEL_DEGREE参数设置。“PARALLEL”关键字的用法是在数据查询语句的SELECT关键字后,增加HINT子句来实现。
HINT语法格式如下:
/+ PARALLEL([< 表名>] < 并行任务个数>) /
例如,下面的例子中,即使已经设置了MAX_PARALLEL_DEGREE默认值3,但实际使用的为PARALLEL指定的任务个数4:
SQL> explain SELECT /+ PARALLEL(4) / * FROM SYSOBJECTS;
1 #NSET2: [0, 1694, 396]
2 #LOCAL COLLECT: [0, 1694, 396]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) for_sync(FALSE)
3 #PRJT2: [0, 1694, 396]; exp_num(17), is_atom(FALSE)
4 #CSCN2: [0, 1694, 396]; SYSINDEXSYSOBJECTS(SYSOBJECTS as SYSOBJECTS)
used time: 0.967(ms). Execute id is 0.
另外,每个语句中仅能设置一次并行任务个数,如果设置了多次,则以最后一次设置为准,而且任务个数在全语句中生效。
例如,下面的例子中,使用的并行任务个数为2。
SQL> call sp_set_para_value(1,'MAX_PARALLEL_DEGREE',1);
DMSQL executed successfully
used time: 6.554(ms). Execute id is 211.
SQL> select sf_get_para_value(1,'MAX_PARALLEL_DEGREE');
LINEID SF_GET_PARA_VALUE(1,'MAX_PARALLEL_DEGREE')
---------- ------------------------------------------
1 1
used time: 5.569(ms). Execute id is 212.
SQL> explain SELECT /+ PARALLEL(1) //+ PARALLEL(2) / * FROM SYSOBJECTS;
1 #NSET2: [0, 1694, 396]
2 #LOCAL COLLECT: [0, 1694, 396]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) for_sync(FALSE)
3 #PRJT2: [0, 1694, 396]; exp_num(17), is_atom(FALSE)
4 #CSCN2: [0, 1694, 396]; SYSINDEXSYSOBJECTS(SYSOBJECTS as SYSOBJECTS)
used time: 1.067(ms). Execute id is 0.
这种方式能够为单条查询语句设置额外的并行任务个数,以此来提高某些特殊查询任务的性能。
在执行并行查询任务之前,您需要指定完成该任务的并行工作线程数。值得注意的是,实际使用的线程数并非总是等于并行工作线程数。并行工作线程数是在INI参数中设定的,实际使用并行工作线程数是根据系统的实际状况确定的。
1. 并行工作线程数,在INI参数中设定
首先,使用PARALLEL_POLICY参数来设置并行策略。取值范围:0、1和2,默认值0。其中,0表示不支持并行;1表示自动并行模式;2表示手动并行模式。
当开启本地并行(PARALLEL_POLICY>0)时,使用PARALLEL_THRD_NUM指定本地并行查询使用的线程数,取值范围为1~1024,缺省值为10。需要注意的是,若PARALLEL_POLICY=1,如果PARALLEL_THRD_NUM=1, 则按照CPU个数创建并行线程。
例如,设置并行策略PARALLEL_POLICY为2,即手动设置并行工作线程数;同时,设置并行工作线程数PARALLEL_THRD_NUM为4个。
SQL> call sp_set_para_value(2,'PARALLEL_POLICY',2);
DMSQL executed successfully
used time: 6.942(ms). Execute id is 223.
SQL> call sp_set_para_value(2,'PARALLEL_THRD_NUM',4);
DMSQL executed successfully
used time: 6.871(ms). Execute id is 224.
当然,并非所有的查询都适合使用并行查询。大量占用CPU 周期的查询最适合采用并行查询的功能。例如,大型表的连接查询、大量数据的聚合和大型结果集的排序等都很适合采用并行查询。对于简单查询(常用于事务处理应用程序)而言,执行并行查询所需的额外协调工作会大于潜在的性能提升。所以,数据库管理员在确定是否需要使用并行策略的时候,需要慎重。
2. 实际使用的线程数,达梦数据库会根据每个并行查询操作自动检测
实际使用线程数是数据库在查询计划执行时初始化的时候确定的。也就是说,这不需要用户去干预,而是系统根据并行任务数和实际空闲的并行工作线程数来确定的。此操作所依据的条件如下:首先,检测达梦数据库是否运行在具有多个CPU的计算机上。只有具有多个CPU 的计算机才能使用并行查询。这是一个硬性的限制条件。其次,检测可用的空闲工作线程是否足够。并行查询到底采用多少线程数,除了跟操作的复杂程度相关外,还跟当时的服务器状态相关,如是否有足够的可用的空闲工作线程数量等。每个并行查询操作都要求一定的工作线程数量才能够执行;而且执行并行计划比执行串行计划需要更多的线程,所需要的线程数量也会随着任务个数的提高而增加。当无法满足特定并行查询执行的线程要求时,数据库引擎就会自动减少任务个数,甚至会放弃并行查询而改为串行计划。所以,即使同一个操作在不同时候可能会采用不同的线程数。
例如,即使设置并行工作线程数为4。而实际使用的线程数可能只有3个,或者更少。
使用手动并行模式时,只需要在INI参数中设置好如下2个参数,然后执行并行SQL查询语句时,需手动指定当前并行任务个数。若不指定,将不使用并行。设置的2个参数如下:
PARALLEL_POLICY 2
PARALLEL_THRD_NUM 4
使用自动并行模式时,一般指定如下三个参数:
MAX_PARALLEL_DEGREE 3
PARALLEL_POLICY 1
PARALLEL_THRD_NUM 10
另外,当PARALLEL_POLICY为0时,即使有并行任务,也不支持并行。
然后,执行语法格式类似“SELECT * FROM SYSOBJECTS;”的并行SQL语句即可,本条语句使用默认并行任务数3。
当然,如果单条查询语句不想使用默认并行任务数,可以通过在SQL语句中增加HINT,通过“PARALLEL”关键字来特别指定。此时,执行的并行SQL语句格式为“SELECT /+ PARALLEL(SYSOBJECTS 4) / * FROM SYSOBJECTS;”,本条语句使用的并行任务数为4。