하위 쿼리가 있는 pg_hint_plan
                                            
                                                
                                                
                                                
                                                
                                                
                                                 9081 단어  sqljoinpostgrespghintplan
                    
예시:
drop table demo2, demo1;
create table demo1 ( id bigint primary key, a int, b int, d int);
create table demo2 ( id bigint primary key, a int, b int, d int);
insert into demo1 select generate_series(1,1000), 0, 0, 0 ;
vacuum analyze demo1;
vacuum analyze demo2;
insert into demo1 select generate_series(100000,200000), 0, 0, 0 ;
이제 테이블
demo1에서 1000개의 행을 가져와 demo2로 이동하는 다음 쿼리가 있습니다.explain (costs off, analyze)
WITH del AS(
 DELETE FROM demo1 a
 WHERE a.id in (SELECT id from demo1 my_batch limit 1000)
 RETURNING *
)  INSERT INTO demo2 
   SELECT  id, a, b c
 FROM del;
실행 계획은 다음과 같습니다.
                                               QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Insert on demo2 (actual time=18.627..18.635 rows=0 loops=1)
   CTE del
     ->  Delete on demo1 a (actual time=0.415..17.051 rows=1000 loops=1)
           ->  Hash Semi Join (actual time=0.399..16.534 rows=1000 loops=1)
                 Hash Cond: (a.id = "ANY_subquery".id)
                 ->  Seq Scan on demo1 a (actual time=0.006..10.032 rows=101001 loops=1)
                 ->  Hash (actual time=0.355..0.360 rows=1000 loops=1)
                       Buckets: 1024  Batches: 1  Memory Usage: 79kB
                       ->  Subquery Scan on "ANY_subquery" (actual time=0.006..0.256 rows=1000 loops=1)
                             ->  Limit (actual time=0.003..0.131 rows=1000 loops=1)
                                   ->  Seq Scan on demo1 my_batch (actual time=0.002..0.089 rows=1000 loops=1)
   ->  CTE Scan on del (actual time=0.417..17.282 rows=1000 loops=1)
 Planning Time: 0.247 ms
 Execution Time: 18.702 ms
(14 rows)
postgres=#
이것은
demo1가 해시 조인을 위한 프로브 테이블로 먼저 전체 스캔되기 때문에 그다지 효율적이지 않습니다. 기본적으로 PostgreSQL은 삭제하려는 1000개id를 해시했지만 전체 테이블을 읽어서 찾습니다. 통계가 정확하지 않다고 생각할 수 있습니다. ANALYZE를 실행해 보십시오. 좋아, 하지만 내 목표는 많은 행을 삭제하는 것입니다(1000개 단위로). 전과 후를 분석하고 싶지 않습니다. 이것은 pg_hint_plan가 도움이 되는 곳입니다. 내 쿼리(LIMIT 1000 포함) 설계에 따라 예측 가능한 성능(테이블 크기가 아닌 처리된 행 수에 따른 시간)을 얻기 위해 해당 행에서 중첩 루프가 필요합니다.조인이 삭제할 테이블인
demo1 a 와 1000demo1 my_batch 인 id 사이에 있다고 생각할 수 있지만 /*+ Leading( (my_batch a) ) NestLoop(my_batch a) */ 와 같은 힌트를 얻으려고 하면 성공하지 못할 것입니다.실행 계획을 보십시오. 해시 조인은
Seq Scan on demo1 a 및 Subquery Scan on "ANY_subquery" 두 스캔 사이에 있습니다. 이것은 조인 순서, 방향 및 방법에 사용해야 하는 별칭을 제공합니다: a 및 "ANY_subquery"중첩 루프를 강제로 실행하려는 경우 힌트
NestLoop("ANY_subquery" a)를 추가할 수 있지만 이는 두 테이블 간의 조인이 중첩 루프 조인이어야 한다는 의미일 뿐입니다. 이 힌트에서 별칭의 순서는 중요하지 않습니다. 조인 쌍이 있는 Leading hind가 필요합니다: Leading( ("ANY_subquery" a) )explain (costs off, analyze)
/*+ Leading( ("ANY_subquery" a) ) NestLoop("ANY_subquery" a) */
WITH del AS(
 DELETE FROM demo1 a
 WHERE a.id in (SELECT id from demo1 my_batch limit 1000)
 RETURNING *
)  INSERT INTO demo2 
   SELECT  id, a, b c
 FROM del;
이것이 내가 원하는 계획입니다.
                                                  QUERY PLAN
---------------------------------------------------------------------------------------------------------------
 Insert on demo2 (actual time=4.267..4.268 rows=0 loops=1)
   CTE del
     ->  Delete on demo1 a (actual time=0.521..2.219 rows=1000 loops=1)
           ->  Nested Loop (actual time=0.508..1.701 rows=1000 loops=1)
                 ->  HashAggregate (actual time=0.492..0.641 rows=1000 loops=1)
                       Group Key: "ANY_subquery".id
                       Batches: 1  Memory Usage: 193kB
                       ->  Subquery Scan on "ANY_subquery" (actual time=0.069..0.305 rows=1000 loops=1)
                             ->  Limit (actual time=0.065..0.177 rows=1000 loops=1)
                                   ->  Seq Scan on demo1 my_batch (actual time=0.064..0.134 rows=1000 loops=1)
                 ->  Index Scan using demo1_pkey on demo1 a (actual time=0.001..0.001 rows=1 loops=1000)
                       Index Cond: (id = "ANY_subquery".id)
   ->  CTE Scan on del (actual time=0.523..2.526 rows=1000 loops=1)
 Planning Time: 0.231 ms
 Execution Time: 4.362 ms
(15 rows)
4.362 ms vs. 18.702 ms 가 빨라서 행복하다고 생각하세요? 전혀. 나는 그 밀리 초에 대해 신경 쓰지 않습니다. 이 계획을 선호하는 이유는 확장성입니다. 여기서는 소스 테이블의 크기에 따라 달라지는 작업이 없습니다. 내 힌트 덕분에 오래된 통계로 인해 O(N) 없음으로 전환할 위험이 없는 O(1) 복잡성을 보장합니다.이 예제는 PostgreSQL(
pg_hint_plan 확장 포함) 또는 호환 가능(pg_hint_plan이 기본적으로 설치된 YugabyteDB와 같은)에서 실행됩니다.
                Reference
이 문제에 관하여(하위 쿼리가 있는 pg_hint_plan), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aws-heroes/pghintplan-with-subqueries-47nm텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)