为什么我的并发查询不用期望的线程数?
为什么我的并发查询不用期望的线程数?
适用范围和应用
大众、数据库管理员,在线支持工程师
单词“查询”可以用在任何类型的sql语句中。单词组“parallel execution slave” 'parallel slave', 'slave',
'parallel execution server' 指的都是同一个概念。这篇文章不包括运行在OPS环境中的查询。
目的:
这篇文章解析如果一个查询没有用到期望的并发线程数我们将要做什么检查。第一个检查是:用了多少个线程数。第二个检查是:什么影响了适用的查询线程数。第二个检查是:跟踪本地查询线程。
1、 如何查询用了多少个线程数
1a从当前会话中查询
2b从不同的会话中查询
1a.从当前的会话查询,我们可以用select * from v$pq_sesstat; 输出的结果如同下面这些信息
STATISTIC LAST_QUERY SESSION_TOTAL
------------------------------ ---------- -------------
Queries Parallelized 1 3
DML Parallelized 0 0
DFO Trees 1 3
Server Threads 8 0
Allocation Height 4 0
Allocation Width 1 0
Local Msgs Sent 114 342
Distr Msgs Sent 0 0
Local Msgs Recv'd 114 342
Distr Msgs Recv'd 0 0
看LAST_QUERY这一列,如果这个'Queries Parallelized'的值大于0,说明上次查询是多线程,'Server Threads'值就是上次多线程查询所用到的线程数,'Allocation Height' 分配高度-实例的并行度,'Allocation Width' 分配宽度-涉及的实例数量,并行度为4并且查询的并发线程为8,我们得出的结论就是2个线程被使用
线程是成组被设置的。要么是1或者2,取决于查询的复杂性。线程设置数可以参考“Parallelizing SQL
statements”这本书的第24章第一节。查询的线程深度定义了每组线程个数的设置。
1b.从不同的会话
当查询语句在运行的时候,执行select sid, qcsid, degree, req_degree from v$px_session order by qcsid; 查询语句
例如:
SID QCSID DEGREE REQ_DEGREE
---------- ---------- ---------- ----------
11 11 20 11 4 4 )
19 11 4 4 )
18 11 4 4 )
17 11 4 4 ) - the slave
16 11 4 4 ) sessions
13 11 4 4 )
12 11 4 4 )
15 11 4 4 )
有那么一行专门进协调分配的线程。你可以跟协调的线程进行匹配。对于匹配的线程来说,SID和QCSID是一样的。对于每个线程来说,SID在每个时间段是不同的。
2.什么会影响查询时用到的线程数
在create or alter table/index 语句的时候可能会视图运行多线程,用并发查询时候可能会用到并发执行,在用alter session语句时候可能会用到并发。
Create和alter语句设置对象的并发属性。这些属性是degree,节点的并发,实例,节点个数。为了能够并发,设置degree属性,如果适当的话,可是设置设置实例个数大于1
在oracle 8i时,可以用到PARALLEL ( DEGREE|INSTANCES integer|DEFAULT),但是现在也可以以前的语句,因为是向下兼容的
在non-OPS环境中,在8i中设置并发属性将会导致degree属性直接被设置成默认,并且实例属性将会被设置成1
即使OPS不被使用,将实例设置大于1或者设置成默认也是可能的。实例的值在8i版本或更高的版本中将会被计算,并且将会导致意外的结果。这不是在以前的版本。看下面的深度和实例被用来计算DOP并且DOP是如何受默认值所影响。
如果并发被切换到任何一个查询对象,接下来的事情就是要确定使用并发。影响并发的规则和并发的适用性,主要取决于他是是否是select,update,delete,insert,select或者DDL。这些使用规则可以查看“Parallel Execution of SQL Statements”的23章第二节。
在8i中,DOP用公式degree * instances计算。这意味着对一个深度设置成1实例设置成5的对象进行查询,将会运行在5个线程的并发模式下。在8i以前,查询将会运行在串行模式下
线程请求使用数量取决于运行的环境。下面几个因数将要影响运行环境
1.the parameter PARALLEL_MAX_SERVERS
2. the parameter PARALLEL_MIN_PERCENT
3. the parameter PARALLEL_AUTOMATIC_TUNING
4. the parameter PARALLEL_ADAPTIVE_MULTI_USER
5. Resource Manager
1. PARALLEL_MAX_SERVERS
这是最大的查询线程数量可以在实例启动的时候。在同一时间每个线程紧能为参与一个查询。如果最大数量已经被用,一些并发查询过将不得不运行在串行模式。如果一个线程完成了一个查询,她将会别另外一个会话使用。如果会话5分钟内不被使用,这个线程将会被终止掉。看有多少当前运行的线程,可以查看v$pq_slave试图。
2. PARALLEL_MIN_PERCENT
这个参数的最小线程百分比就是要被要求运行在多线程查询下。如果被设置成0,表示没有最低的并发线程被要求。如果被设置成100,查询将会失败直到所有的线程都被找到。如果在0到100之间设置,查询将会失败直到这个百分比的查询线程被启动。
3. PARALLEL_AUTOMATIC_TUNING
从10g以后的版本,默认的参数PARALLEL_ADAPTIVE_MULTI_USER被设置成true。PARALLEL_MAX_SERVERS参数也由原先的5改成现在根据CPU个数,以及PARALLEL_AUTOMATIC_TUNING来计算
4、PARALLEL_ADAPTIVE_MULTI_USER
PARALLEL_ADAPTIVE_MULTI_USER参数设置的公式是PARALLEL_THREADS_PER_CPU * CPU_COUNT * (a reduction factor) 。取决于当前运行并发查询的用户。这个在例子3中描述。当大量的并发查询发生,而分配给本地的线程数减少,将会迫使系统运行在串行模式下或者报错。
5、Resource Manager
用资源管理器可以限制魅族用户的并发深度。
3、如何跟踪本地查询的线程数
在所有的数据库版本中,你都可以用事件10293来跟中本地的线程数。这个将会显示本地现在又多少个线程被请求。可以执行alter session set events '10392 trace name context forever, level 1';进行跟踪模式的切换。执行 alter session set events '10392 trace name context off';
关闭跟踪模式。在DEPT表上的深度是1,而在EMP表上的深度并发是改变的在每个实例上。因为查询包含了一个统计和排序,连个线程就会被用到。因此我们期望总的线程数被设置为2.
例题1:
表EMP有一个并发深度1. PARALLEL_MAX_SERVERS = 8.跟踪文件将会显示如下的信息
-------------------------------- Beginning of trace ---------------------------------------
1 *** 2002-04-26 11:59:28.415
2 *** SESSION ID:(9.37435) 2002-04-26 11:59:28.375
3 kxfpgsg: getting 2 sets of 5 threads, client parallel query execution flg=0x30
4 : Height=5, Affinity List Size=0, inst_total=1, coord=1
5 : Insts 1
6 : Threads 5
7 kxfpg1srv: trying to get slave P000 on instance 1
8 g1sg: Got It. 1 so far.
9 kxfpg1srv: trying to get slave P001 on instance 1
10 g1sg: Got It. 2 so far.
11 kxfpg1srv: trying to get slave P002 on instance 1
12 g1sg: Got It. 3 so far.
13 kxfpg1srv: trying to get slave P003 on instance 1
14 g1sg: Got It. 4 so far.
15 kxfpg1srv: trying to get slave P004 on instance 1
16 g1sg: Got It. 5 so far.
17 got 5 servers (sync), returning...
18 kxfpg1srv: trying to get slave P000 on instance 1
19 kxfpg1srv: trying to get slave P001 on instance 1
20 kxfpg1srv: trying to get slave P002 on instance 1
21 kxfpg1srv: trying to get slave P003 on instance 1
22 kxfpg1srv: trying to get slave P004 on instance 1
23 kxfpg1srv: trying to get slave P005 on instance 1
24 g1sg: Got It. 1 so far.
25 kxfpg1srv: trying to get slave P006 on instance 1
26 g1sg: Got It. 2 so far.
27 kxfpg1srv: trying to get slave P007 on instance 1
28 g1sg: Got It. 3 so far.
29 got 3 servers (sync), returning...
30 kxfpgsg: got 4 threads on 1 instance(s), avg height=4
31 : Insts 1
32 : Svrs 8
33 kxfpgsg: Freeing Memory: il=0x157900e8 iload=0x157900bc ilist=0x0 slist=0x0
34 kxfplsig: signaling OER(10382) in serial 2560
35 kxfplsig: dp 0x33433a0, q 0x5f6ffdc, pr 0x2d1f484, cqr 0x5f67aa8, err 0
36-42 above line repeated for each slave
43 kxfplsig: signaling OER(10387) in serial 2560
44 kxfplsig: dp 0x33433a0, q 0x5f6ffdc, pr 0x2d1f484, cqr 0x5f67aa8, err 0
45-51 above line repeated for each slave
52 kxfpqsrls: Release Slave q=0x5f7271c qr=0x5f680d4 action=1 slave=7 inst=1
53-59 above line repeated for each slave
-------------------------------End of Trace-------------------------------------------------
跟踪文件中,3-6行协调员请求5个线程,7-17行5个线程分配成功,18-22行协调员检查这5个线程保证是可用的,23-29行另外3个线程被分配,30-32行协调员重新计算线程数并设置为4。其余的跟踪文件显示每个线程是独立的并且发布查询的结果
例子2:
表EMP有一个并发深度10设置,PARALLEL_AUTOMATIC_TUNING = TRUE。本地的跟踪文件内容如下结果相识。
1 *** 2002-05-16 14:37:32.424
2 *** SESSION ID:(12.36) 2002-05-16 14:37:32.394
3 kxfpgsg: getting 2 sets of 7 threads, client parallel query execution flg=0x30
4 : threads reduced from 10 to 7
5 : Height=7, Affinity List Size=0, inst_total=1, coord=1
6 : Insts 1
7 : Threads 7
在第四行,预期设置的线程数10被减到7,是因为parallel_adaptive_multi_user参数设置成了 TRUE
例子3:
Init.ora配置文件中的参数与例子2中时一样的。表EMP有一个默认的并发深度设置。本地的跟踪文件如下所示
1 *** 2002-05-16 15:51:10.737
2 *** SESSION ID:(11.5) 2002-05-16 15:51:10.737
3 kxfpiinfo: inst[cpus:mxslv]
4 : 1[4:40]
5 kxfpclinfo: inst(load:user:pct:fact)aff
6 : 1(4:0:100:100)
7 kxfpAdaptDOP: Requested=8 Granted=7 Target=16 Load=4 Default=8 users=0 sets=2
8 kxfpgsg: getting 2 sets of 7 threads, client parallel query execution flg=0x30
9 : threads reduced from 8 to 7
10 : Height=7, Affinity List Size=0, inst_total=1, coord=1
11 : Insts 1
12 : Threads 7
第3-4行,我们看到一些参考数据显示为:inst (# of instances) =1, cpus=4, mxslv (parallel_max_servers) =40。在5-6行,有一个负载4在数据库上,这个负载是活动的服务器线程数。7行,我们看到协调员请求的8个线程,基于PARALLEL_THREADS_PER_CPU * CPU_COUNT。仅仅分配7个,是由于削减因素在9行显示。从2,3两个例子可以看出PARALLEL_ADAPTIVE_MULTI_USER = TRUE这个参数可以导致已经设置好的对象参数在查询的时候又进行了削减。
例子4:
表EMP有一个并发深度设置8.用户有一个4的深度限制,在资源管理器中设置。跟踪文件如下所示
1 *** 2004-04-07 14:27:43.536
2 *** SESSION ID:(7.11) 2004-04-07 14:27:43.466
3 kxfpgsg
4 getting 1 sets of 4 threads, client parallel query execution flg=0x30
5 threads reduced from 8 to 4
6 Height=4, Affinity List Size=0, inst_total=1, coord=1
7 Insts 1
8 Threads 4
在5行显示深度设置从8削减到4。当查询运行在单线程的时候,你将不会得到跟踪文件