故障处理:event enq: JZ – Join group dictionary when in-memory disable

我们的文章会在微信公众号IT民工的龙马人生博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。

本文转自朋友的真实案例分享。

event enq: JZ – Join group dictionary when in-memory disable

该问题由MES平台的一个客户提出,某些sql会等待event enq: JZ – Join group dictionary,该等待事件比较冷门,也不确认是否会有隐患。所以让我们来分析一下。

通常我分析不熟悉的enqueue时,通常都会查询v$lock_type,可以简要的了解到该队列的含义。

SQL> select type,name,description from v$lock_type where type='JZ';
 
TYPE                 NAME                           DESCRIPTION
-------------------- ------------------------------ ----------------------------------------------------------------------------------------------------
JZ                   Join group dictionary          Synchronizes modifications to im_domain$ and im_joingroup$

可以看到JZ队列是为了串行的维护im_domain$和im_joingroup$,这两个基表与in-memory有关。具体特性与功能参考https://docs.oracle.com/en/database/oracle/oracle-database/19/inmem/optimizing-queries-with-join-groups.html。

当create join group或者drop join group时,会请求JZ队列锁,这一点应该很容易理解。

但是客户的环境在in-memory并未启用,并且并未create join group的情况下,仍然会出现等待事件enq: JZ – Join group dictionary。

通过研究发现,当使用了hash join的时候,也会请求JZ队列锁。由隐藏参数_sqlexec_join_group_aware_hj_enabled控制。

test demo:

SQL> @sp join_group
 
-- show parameter by sp
 
-- show hidden parameter by sp
old   3: where x.indx=y.indx and ksppinm like '_%&p%'
new   3: where x.indx=y.indx and ksppinm like '_%join_group%'
 
NAME                                     VALUE      DESC
---------------------------------------- ---------- ------------------------------------------------------------------------------------------
_sqlexec_join_group_aware_hj_enabled     TRUE       enable/disable join group aware hash join
_sqlexec_join_group_aware_hj_unencoded_r 50         minimum number of unencoded rowsets processed before adaptation
owsets_tolerated
 
SQL> @sp inmemory_size
 
-- show parameter by sp
 
NAME                                 TYPE       VALUE
------------------------------------ ---------- ------------------------------
inmemory_size                        big intege 0
 
 
SQL> select count(*) from im_joingroup$;
 
  COUNT(*)
----------
         0
 
SQL> select count(*) from im_domain$;
 
  COUNT(*)
----------
         0
                                     
SQL> explain plan for select count(*) from test.t,test.t1 where t.object_name=t1.object_name;
 
Explained.
 
SQL> select * from table(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2895516660
 
------------------------------------------------------------------------------------
| Id  | Operation           | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |     1 |    70 |       |  1118   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE     |      |     1 |    70 |       |            |          |
|*  2 |   HASH JOIN         |      | 87256 |  5964K|  3352K|  1118   (1)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| T    | 73021 |  2495K|       |   396   (1)| 00:00:01 |
|   4 |    TABLE ACCESS FULL| T1   | 73021 |  2495K|       |   396   (1)| 00:00:01 |
------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("T"."OBJECT_NAME"="T1"."OBJECT_NAME")
 
SQL>  select count(*) from test.t,test.t1 where t.object_name=t1.object_name;
 
  COUNT(*)
----------
    110615
 
SQL> select * from v$enqueue_stat where rownum=1  and eq_type='JZ';
 
   INST_ID EQ TOTAL_REQ# TOTAL_WAIT#  SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME     CON_ID
---------- -- ---------- ----------- ---------- ----------- ------------- ----------
         1 JZ          1           0          1           0             0          0
 
SQL> select count(*) from test.t,test.t1 where t.object_name=t1.object_name;
 
  COUNT(*)
----------
    110615
 
SQL> select * from v$enqueue_stat where rownum=1  and eq_type='JZ';
 
   INST_ID EQ TOTAL_REQ# TOTAL_WAIT#  SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME     CON_ID
---------- -- ---------- ----------- ---------- ----------- ------------- ----------
         1 JZ          2           0          2           0             0          0
 
SQL> alter session set "_sqlexec_join_group_aware_hj_enabled"=false;
 
Session altered.
 
SQL>  select count(*) from test.t,test.t1 where t.object_name=t1.object_name;
 
  COUNT(*)
----------
    110615
 
SQL> select * from v$enqueue_stat where rownum=1  and eq_type='JZ';
 
   INST_ID EQ TOTAL_REQ# TOTAL_WAIT#  SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME     CON_ID
---------- -- ---------- ----------- ---------- ----------- ------------- ----------
         1 JZ          2           0          2           0             0          0

如果没有出现性能问题的话,并不建议关闭_sqlexec_join_group_aware_hj_enabled。

不过个人猜测HASH JOIN请求的JZ锁应该是共享的,之所以会阻塞还是可能有排他模式的请求,分析队列锁,最好还是使用10046+10704 event去分析。

------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)

posted @ 2025-07-31 16:11  认真就输  阅读(9)  评论(0)    收藏  举报