Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
强制PostgreSQL在查询中使用哈希联接_Postgresql_Performance - Fatal编程技术网

强制PostgreSQL在查询中使用哈希联接

强制PostgreSQL在查询中使用哈希联接,postgresql,performance,Postgresql,Performance,我正在做一些性能调整,postgres日志中出现了一个特定的查询 粘贴在下面的查询: select distinct sc.CAPABILITY_NAME as "CAPABILITY" from SYSTEM_CAPABILITY sc join ROLE_CAPABILITY urc on urc.CAPABILITY=sc.CAPABILITY_NAME join ROLE_CAPABILITY grc on grc.CAPABILITY=urc.CAPABILITY

我正在做一些性能调整,postgres日志中出现了一个特定的查询

粘贴在下面的查询:

select distinct sc.CAPABILITY_NAME as "CAPABILITY" from SYSTEM_CAPABILITY sc join ROLE_CAPABILITY urc on urc.CAPABILITY=sc.CAPABILITY_NAME join ROLE_CAPABILITY grc on grc.CAPABILITY=urc.CAPABILITY join GROUP_USER gu on gu.ROLE=urc.ROLE_NAME join GROUP_ROLE gr on gr.ROLE_NAME=grc.ROLE_NAME where gu.USERNAME='TEST123' and (gu.EXPIRY_DATE is null or gu.EXPIRY_DATE>'2020-11-17 00:00:00+01') and gr.ID=gu.GROUP_ID and gu.GROUP_ID='ABC123'
当我直接对数据库运行这个查询时,需要几毫秒,但是当它从Java应用程序运行时,需要2秒钟以上

我在postgres配置文件中启用了以下选项。 会话\u预加载\u库='auto\u explain' auto_explain.log_min_duration='1s'

从my local运行查询时,我可以看到,与Java应用程序的运行相比,my local使用哈希连接,而Java应用程序的运行使用嵌套循环

然后,我启用了设置enable_hashjoin=on作为测试,但看起来通过Java应用程序的测试仍然使用嵌套循环。我在运行Java应用程序的同时运行了这个查询,但只需要17ms,并且使用了hash_连接

首先,对postgres配置文件进行这样的更改是明智的。我理解,这也可能影响其他查询,目前更像是评估影响的测试阶段

其次,除了设置enable_hashjoin=on之外,我还需要做些什么来防止嵌套循环成为查询的第一个调用点

自动解释的查询结果如下:

Java应用程序

< 2020-11-18 10:55:57.012 CET >LOG:  duration: 2212.992 ms  execute S_107:  select distinct sc.CAPABILITY_NAME as "CAPABILITY" from SYSTEM_CAPABILITY sc join ROLE_CAPABILITY urc on urc.CAPABILITY=sc.CAPABILITY_NAME join ROLE_CAPABILITY grc on grc.CAPABILITY=urc.CAPABILITY join GROUP_USER gu on gu.ROLE=urc.ROLE_NAME join GROUP_ROLE gr on gr.ROLE_NAME=grc.ROLE_NAME where gu.USERNAME=$1 and (gu.EXPIRY_DATE is null or gu.EXPIRY_DATE>$2) and gr.ID=gu.GROUP_ID and gu.GROUP_ID=$3
< 2020-11-18 10:55:57.012 CET >DETAIL:  parameters: $1 = 'TEST123', $2 = '2020-11-17 00:00:00+01', $3 = 'ABC123'
< 2020-11-18 10:55:57.014 CET >LOG:  duration: 2212.984 ms  plan:
    Query Text:  select distinct sc.CAPABILITY_NAME as "CAPABILITY" from SYSTEM_CAPABILITY sc join ROLE_CAPABILITY urc on urc.CAPABILITY=sc.CAPABILITY_NAME join ROLE_CAPABILITY grc on grc.CAPABILITY=urc.CAPABILITY join GROUP_USER gu on gu.ROLE=urc.ROLE_NAME join GROUP_ROLE gr on gr.ROLE_NAME=grc.ROLE_NAME where gu.USERNAME=$1 and (gu.EXPIRY_DATE is null or gu.EXPIRY_DATE>$2) and gr.ID=gu.GROUP_ID and gu.GROUP_ID=$3
    HashAggregate  (cost=78.40..78.44 rows=4 width=19)
      Group Key: sc.capability_name
      ->  Nested Loop  (cost=5.49..78.39 rows=4 width=19)
            ->  Nested Loop  (cost=5.22..77.12 rows=4 width=38)
                  Join Filter: ((gu.role)::text = (urc.role_name)::text)
                  ->  Nested Loop  (cost=4.93..62.56 rows=30 width=36)
                        ->  Nested Loop  (cost=0.42..9.82 rows=1 width=85)
                              ->  Index Only Scan using idx_gp_usr_gp_usrnm_rl_exp_dt on group_user gu  (cost=0.42..8.46 rows=1 width=26)
                                    Index Cond: ((group_id = ($3)::text) AND (username = ($1)::text))
                                    Filter: ((expiry_date IS NULL) OR (expiry_date > $2))
                              ->  Seq Scan on group_role gr  (cost=0.00..1.35 rows=1 width=112)
                                    Filter: ((id)::text = ($3)::text)
                        ->  Bitmap Heap Scan on role_capability grc  (cost=4.51..52.44 rows=30 width=33)
                              Recheck Cond: ((role_name)::text = (gr.role_name)::text)
                              ->  Bitmap Index Scan on pk_role_capability  (cost=0.00..4.51 rows=30 width=0)
                                    Index Cond: ((role_name)::text = (gr.role_name)::text)
                  ->  Index Scan using idx_role_capability_capability on role_capability urc  (cost=0.28..0.42 rows=5 width=33)
                        Index Cond: ((capability)::text = (grc.capability)::text)
            ->  Index Only Scan using idx_system_capability_capability_name on system_capability sc  (cost=0.28..0.31 rows=1 width=19)
                  Index Cond: (capability_name = (urc.capability)::text)
<2020-11-18 10:55:57.012 CET>日志:持续时间:2212.992毫秒执行S_107:选择不同的sc.CAPABILITY_名称作为“CAPABILITY”从系统能力sc加入角色能力urc上的urc.CAPABILITY=sc.CAPABILITY\u NAME加入角色能力grc上的grc.CAPABILITY=urc.CAPABILITY加入组用户gu上gu.ROLE=urc.ROLE\u NAME加入组角色gr上gr.ROLE\u NAME=grc.ROLE\u NAME,其中gu.USERNAME=$1和(gu.expiration\u日期为空或gu.expiration\u日期>$2)gr.ID=gu.GROUP\U ID和gu.GROUP\U ID=3美元
<2020-11-18 10:55:57.012 CET>详细信息:参数:$1='TEST123',$2='2020-11-17 00:00:00+01',$3='ABC123'
<2020-11-18 10:55:57.014 CET>日志:持续时间:2212.984毫秒计划:
查询文本:从系统中选择不同的sc.CAPABILITY\u名称作为“CAPABILITY”,sc-CAPABILITY-join-ROLE\u-NAME-join-ROLE\u-CAPABILITY-grc-on-grc.CAPABILITY=urc.CAPABILITY-join-GROUP\u-USER-gu-on-gu.ROLE=urc.ROLE\u-NAME-join-GROUP\u-ROLE-gr-on-ROLE\u-NAME其中gu.USERNAME=$1和(gu.expiration\u DATE为null或gu.expiration\u DATE>$2)且gr.ID=gu.GROUP\u ID和gu.GROUP\u ID=$3
HashAggregate(成本=78.40..78.44行=4宽度=19)
组密钥:sc.capability\u name
->嵌套循环(成本=5.49..78.39行=4宽度=19)
->嵌套循环(成本=5.22..77.12行=4宽度=38)
加入筛选器:((gu.role)::text=(urc.role\u名称)::text)
->嵌套循环(成本=4.93..62.56行=30宽度=36)
->嵌套循环(成本=0.42..9.82行=1宽度=85)
->使用组用户gu上的idx_gp_usr_gp_usrnm_rl_exp_dt仅索引扫描(成本=0.42..8.46行=1宽度=26)
索引条件:((组id=($3)::文本)和(用户名=($1::文本))
筛选器:((到期日为空)或(到期日>$2))
->组角色gr上的顺序扫描(成本=0.00..1.35行=1宽度=112)
筛选器:((id)::text=($3)::text)
->角色功能grc上的位图堆扫描(成本=4.51..52.44行=30宽度=33)
重新检查条件:((角色名称)::text=(组角色名称)::text)
->pk_角色_功能上的位图索引扫描(成本=0.00..4.51行=30宽度=0)
索引条件:((角色名称)::文本=(组角色名称)::文本)
->在角色能力urc上使用idx角色能力进行索引扫描(成本=0.28..0.42行=5宽度=33)
索引条件:((能力)::文本=(grc.能力)::文本)
->在system_capability sc上使用idx_system_capability_名称仅索引扫描(成本=0.28..0.31行=1宽度=19)
索引条件:(能力名称=(资源能力)::文本)
从连接到DB的本地计算机运行

< 2020-11-18 10:58:50.297 CET >LOG:  duration: 16.070 ms  plan:
    Query Text: 
    select distinct sc.CAPABILITY_NAME as "CAPABILITY" from SYSTEM_CAPABILITY sc join ROLE_CAPABILITY urc on urc.CAPABILITY=sc.CAPABILITY_NAME join ROLE_CAPABILITY grc on grc.CAPABILITY=urc.CAPABILITY join GROUP_USER gu on gu.ROLE=urc.ROLE_NAME join GROUP_ROLE gr on gr.ROLE_NAME=grc.ROLE_NAME where gu.USERNAME='TEST123' and (gu.EXPIRY_DATE is null or gu.EXPIRY_DATE>'2020-11-17 00:00:00+01') and gr.ID=gu.GROUP_ID and gu.GROUP_ID='ABC123'
    
    HashAggregate  (cost=93.77..94.27 rows=50 width=19) (actual time=15.997..16.021 rows=200 loops=1)
      Group Key: sc.capability_name
      ->  Hash Join  (cost=16.86..93.65 rows=50 width=19) (actual time=0.325..15.295 rows=2329 loops=1)
            Hash Cond: ((urc.role_name)::text = (gu.role)::text)
            ->  Nested Loop  (cost=5.07..78.20 rows=169 width=77) (actual time=0.139..14.106 rows=5861 loops=1)
                  Join Filter: ((sc.capability_name)::text = (urc.capability)::text)
                  ->  Nested Loop  (cost=4.79..63.64 rows=30 width=82) (actual time=0.132..5.677 rows=1076 loops=1)
                        ->  Nested Loop  (cost=4.51..54.09 rows=30 width=63) (actual time=0.124..0.447 rows=1076 loops=1)
                              ->  Seq Scan on group_role gr  (cost=0.00..1.35 rows=1 width=112) (actual time=0.015..0.018 rows=1 loops=1)
                                    Filter: ((id)::text = 'ABC123'::text)
                                    Rows Removed by Filter: 27
                              ->  Bitmap Heap Scan on role_capability grc  (cost=4.51..52.44 rows=30 width=33) (actual time=0.107..0.302 rows=1076 loops=1)
                                    Recheck Cond: ((role_name)::text = (gr.role_name)::text)
                                    Heap Blocks: exact=37
                                    ->  Bitmap Index Scan on pk_role_capability  (cost=0.00..4.51 rows=30 width=0) (actual time=0.098..0.098 rows=1076 loops=1)
                                          Index Cond: ((role_name)::text = (gr.role_name)::text)
                        ->  Index Only Scan using idx_system_capability_capability_name on system_capability sc  (cost=0.28..0.31 rows=1 width=19) (actual time=0.004..0.005 rows=1 loops=1076)
                              Index Cond: (capability_name = (grc.capability)::text)
                              Heap Fetches: 1076
                  ->  Index Scan using idx_role_capability_capability on role_capability urc  (cost=0.28..0.42 rows=5 width=33) (actual time=0.005..0.007 rows=5 loops=1076)
                        Index Cond: ((capability)::text = (grc.capability)::text)
            ->  Hash  (cost=11.62..11.62 rows=13 width=26) (actual time=0.179..0.179 rows=279 loops=1)
                  Buckets: 1024  Batches: 1  Memory Usage: 24kB
                  ->  Index Only Scan using idx_gp_usr_gp_usrnm_rl_exp_dt on group_user gu  (cost=0.42..11.62 rows=13 width=26) (actual time=0.023..0.110 rows=279 loops=1)
                        Index Cond: ((group_id = 'ABC123'::text) AND (username = 'TEST123'::text))
                        Filter: ((expiry_date IS NULL) OR (expiry_date > '2020-11-16 23:00:00+00'::timestamp with time zone))
                        Heap Fetches: 4
<2020-11-18 10:58:50.297 CET>日志:持续时间:16.070毫秒计划:
查询文本:
从系统中选择不同的sc.CAPABILITY\u NAME作为“CAPABILITY”,sc加入角色\u能力urc在urc上。CAPABILITY=sc.CAPABILITY\u NAME加入角色\u能力grc在grc上。CAPABILITY=urc.CAPABILITY加入组\u用户gu在gu上。ROLE=urc.ROLE\u NAME加入组\u角色gr在gr.ROLE\u NAME=grc.ROLE\u名称,其中gu.USERNAME='TEST123'和(gu.expiration\u DATE为空或gu.expiration\u DATE>'2020-11-17 00:00:00+01')且gr.ID=gu.GROUP\u ID和gu.GROUP\u ID='ABC123'
HashAggregate(成本=93.77..94.27行=50宽度=19)(实际时间=15.997..16.021行=200循环=1)
组密钥:sc.capability\u name
->散列联接(成本=16.86..93.65行=50宽度=19)(实际时间=0.325..15.295行=2329循环=1)
散列条件:((urc.role_名称)::text=(gu.role)::text)
->嵌套循环(成本=5.07..78.20行=169宽度=77)(实际时间=0.139..14.106行=5861循环=1)
连接筛选器:((sc.capability_name)::text=(urc.capability)::text)
->嵌套循环(成本=4.79..63.64行=30宽度=82)(实际时间=0.132..5.677行=1076个循环=1)
->嵌套循环(成本=4.51..54.09行=30宽度=63)(实际时间=0.124..0.447行=1076个循环=1)
->对组角色gr的顺序扫描(成本=0.00..1.35行=1宽度=112)(实际时间=0.015..0.018行=1圈=1)
筛选器:((id)::text='ABC123'::text)
被筛选器删除的行:27
->角色功能grc上的位图堆扫描(成本=4.51..52.44行=30宽度=33)(实际时间=0.107..0.302行=1076循环=1)
复查条件