pg hint 계획 및 단일 테이블 기준 수정
11528 단어 databasesqlpostgresyugabytedb
$ psql postgres://franck:[email protected]:5433/yb_demo_northwind
psql (14beta1, server 11.2-YB-2.7.1.1-b0)
Type "help" for help.
yb_demo_northwind=>
이것은 우리가 통계 데이터가 없는 예다.분산 문서 저장소(DocDB)를 PostgreSQL에 삽입하여 외부 데이터 패키지를 통해 조회하는 데 사용합니다YugabyteDB.나는 주제에 대한 관심을 유지하기 위해 이곳의 일을 지나치게 간소화했다.관건은 현재 버전(YB-2.7)에서 우리는 표 통계 정보가 없고 조회 계획기는 기본 1000줄을 사용한다.
yb_demo_northwind=> explain (analyze, summary false) select * from orders;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Seq Scan on orders (cost=0.00..100.00 rows=1000 width=472) (actual time=128.102..129.019 rows=830 loops=1)
(1 row)
yb_demo_northwind=> explain (analyze, summary false) select * from orders where ship_country='Switzerland';
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Seq Scan on orders (cost=0.00..102.50 rows=1000 width=472) (actual time=90.315..91.300 rows=18 loops=1)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 812
(3 rows)
EXPLAIN 및 다음을 사용합니다.pg 프롬프트 계획
PostgreSQL에서 pg hint plan 확장을 설치하고 활성화해야 합니다.PostgreSQL 커뮤니티는 잘못 사용될까 봐 걱정하고, 검색 계획기를 유지하는 커뮤니티에 최적화기가 오류를 평가할 때 발생하는 문제를 보고하지 않는다.위험은 사람들이 암시를 통해서만 문제를 해결할 뿐 근본적인 원인을 해결하지 못한다는 데 있다.설령 개원된 것이라 할지라도Yugabyte 서로 다른 위치에 있다.사용자는 이 데이터베이스가 새롭고 매우 활발한 개발 중이며 Slack 또는 GitHub를 통해 우리와 상호작용을 하고 있음을 알고 있다.그리고 힌트를 사용하여 서로 다른 계획을 테스트하고 문제를 보고하며 힌트를 단기 해결 방안에 남겨 두었다.이외에도 YugabyteDB는 easyrolling upgrade를 지원하는 분포식 데이터베이스이기 때문에 고정 버전은 정지하지 않고 배치하기 쉽다.
YugabyteDB에서는 기본적으로 pg hint 스케줄을 설치하고 활성화합니다.
yb_demo_northwind=> show pg_hint_plan.enable_hint;
pg_hint_plan.enable_hint
-------------------------------
on
(1 row)
yb_demo_northwind=> show pg_hint_plan.message_level;
pg_hint_plan.message_level
---------------------------------
log
(1 row)
pg hint plan 확장은 계획 작업(스캔 또는 인덱스 액세스, 연결 순서 및 방법)을 제어하는 프롬프트를 추가할 수 있지만 "Rows"프롬프트를 사용하여 기준 추정치를 수정할 수도 있습니다. Oracle의 OPT ESTIMATE() 프롬프트로 간주할 수 있습니다.그러나 현재 버전에서는 pg hint plan Rows() hint가 연결 결과만 조작합니다.yb_demo_northwind=> explain (analyze, summary false) select /*+ Rows(o #42) */ * from orders o where ship_country='Switzerland';
INFO: pg_hint_plan: hint syntax error at or near " "
DETAIL: Rows hint requires at least two relations.
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------
Seq Scan on orders o (cost=0.00..102.50 rows=1000 width=472) (actual time=26.114..27.103 rows=18 loops=1)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 812
(3 rows)
이것은 문법 오류를 표시하고 알림을 무시합니다.프롬프트를 사용할 때는 항상 메시지를 보고 결과를 확인합니다.여기에 나는 여전히 기본 줄 = 1000을 가지고 있다.단표 기수
나는 이곳에서 글을 쓰는 것이 조금도 만족스럽지 않다.단기적인 해결 방안을 언급하여 더 좋은 방법이 있거나 pg hint 계획에 이 기수 수정을 추가하는 데 도움이 될 수 있는지 살펴보겠습니다.그리고 어쨌든 그 결과를 알았을 때 추악한 변통 방법은 잠시 사용할 수 있다.
yb_demo_northwind=> explain (analyze, summary false)
/*+ Leading(dummy o) Rows(dummy o #42) */
select * from (select 1 limit 1) dummy, orders o where ship_country='Switzerland';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.00..112.52 rows=42 width=476) (actual time=24.733..25.807 rows=18 loops=1)
-> Limit (cost=0.00..0.01 rows=1 width=4) (actual time=0.671..0.673 rows=1 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.001..0.001 rows=1 loops=1)
-> Seq Scan on orders o (cost=0.00..102.50 rows=1000 width=472) (actual time=23.997..25.066 rows=18 loops=1)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 812
(6 rows)
yb_demo_northwind=> explain (analyze, summary false)
/*+ Leading(dummy o) Rows(dummy o #42) */
with dummy as (values (1))
select o.* from dummy, orders o where ship_country='Switzerland';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.01..112.53 rows=42 width=472) (actual time=24.089..25.115 rows=18 loops=1)
CTE dummy
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.001..0.002 rows=1 loops=1)
-> CTE Scan on dummy (cost=0.00..0.02 rows=1 width=0) (actual time=0.004..0.005 rows=1 loops=1)
-> Seq Scan on orders o (cost=0.00..102.50 rows=1000 width=472) (actual time=24.070..25.091 rows=18 loops=1)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 812
(7 rows)
subselect와 with 자문(CTE)에서 두 가지 변체를 볼 수 있다.이 두 가지 방법은 모두 끼워 넣는 순환을 추가하여 실제 원가를 무시할 수 있어도 예상 원가의 기초 위에서 10을 증가시킬 것이다.Rows()는 절대 값이 아닌 보정을 수행할 수 있습니다.만약 당신이 이미 통계 데이터가 있는 표에서 그것을 사용한다면, 예상 원가를 조정하여 표의 증가를 따르게 하고, 수정을 유지하는 것이 가장 좋다.만나다pg_hint_plan documentation
한 시계의 정정은 아마도 매우 유용하지 않을 것이다.그러나 진일보한 가입이 있을 때 큰 영향을 미친다.
다음 예는 다음과 같습니다.
yb_demo_northwind=> explain (analyze, summary false)
select o.* from orders o join order_details d using (order_id) where ship_country='Switzerland';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.00..218.88 rows=1000 width=472) (actual time=190.386..3890.738 rows=52 loops=1)
-> Seq Scan on order_details d (cost=0.00..100.00 rows=1000 width=2) (actual time=11.991..14.555 rows=2155 loops=1)
-> Index Scan using orders_pkey on orders o (cost=0.00..0.12 rows=1 width=472) (actual time=1.656..1.656 rows=0 loops=2155)
Index Cond: (order_id = d.order_id)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 1
(6 rows)
여기에 통계 데이터가 없기 때문에 조회 계획기는 모든 줄 수가 1000인 표를 추정하고'order details'표부터 시작하기로 결정합니다.그러나 이것은 효율적이지 않다. 모든 주문서의 상세한 정보를 읽고'주문서'에 가입해야'발송국'을 필터할 수 있다.2000개의 순환은 시간을 필요로 하는데, 특히 분포식 데이터베이스에서 줄은 서로 다른 노드에서 나올 수 있다.나는 아주 작은 기계에서 OCI 자유층에서 운행하고 있다. 나는 열린 상태를 유지하기 때문에 연결 문자열을 포함하여 모든 것을 복사하고 붙여넣을 수 있다.물론 YugabyteDB도 쉽게 설치할 수 있습니다: https://docs.yugabyte.com/latest/quick-start
검색 계획기에 "ship country"필터링에 대한 선택성이 높다는 것을 알려 줄 수 있는 유사 줄 (위o*0.2) 의 알림을 추가할 수 있습니다.
yb_demo_northwind=> explain (analyze, summary false)
/*+ Rows(dummy o *0.2) Rows(dummy d *1) */
with dummy as (values (1))
select o.* from dummy, orders o join order_details d using (order_id) where ship_country='Switzerland';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
Hash Join (cost=115.03..220.78 rows=200 width=472) (actual time=32.111..33.552 rows=52 loops=1)
Hash Cond: (d.order_id = o.order_id)
CTE dummy
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.001..0.002 rows=1 loops=1)
-> Seq Scan on order_details d (cost=0.00..100.00 rows=1000 width=2) (actual time=6.930..8.147 rows=2155 loops=1)
-> Hash (cost=112.52..112.52 rows=200 width=472) (actual time=25.141..25.141 rows=18 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 11kB
-> Nested Loop (cost=0.00..112.52 rows=200 width=472) (actual time=24.171..25.123 rows=18 loops=1)
-> CTE Scan on dummy (cost=0.00..0.02 rows=1 width=0) (actual time=0.003..0.004 rows=1 loops=1)
-> Seq Scan on orders o (cost=0.00..102.50 rows=1000 width=472) (actual time=24.139..25.086 rows=18 loops=1)
Filter: ((ship_country)::text = 'Switzerland'::text)
Rows Removed by Filter: 812
여기의 실행 속도가 훨씬 빨라서 "order details"의 중첩 순환을 피할 수 있습니다.모든 '주문 상세 정보' 가 스캔되고 산열되는 것을 놀라게 할 수도 있지만, 이것은 분포식 데이터베이스이며, 이 테이블은 많은 태블릿PC에 분할되어 있다는 것을 기억하십시오.더 낮은 선택성을 사용한다. 예를 들어 줄(위o#5)은'주문서'에서 온 다섯 줄을 최적화시켜 그곳에서 끼워 넣는 순환을 볼 수 있다.Dalibo plan visualizer:이것은 올바른 접근입니다. 이 가상 CTE를 추가하는 것 외에, 제가 해야 할 일은 20%의 알 수 없는 선택성을 언급하는 것입니다."order details"로 시작할 때 줄의 선택성은 100%(가상 d*1)라고 언급했다.이것은 이 내용을 바꾸지 않지만, 중요한 것은 검색 기획기가 고려할 수 있는 모든 연결 순서를 고려하고, 알림이 모든 순서와 일치하는지 확인하는 것입니다.각 주문에 대해 평균 3개의 주문 상세 정보를 제공하는 행(가상 o d*3)을 추가할 수도 있습니다.나는 또한 정확한 숫자를 사용하기로 결정할 수 있다. 예를 들어 행(위o#18)행(위d#2155)행(위d*2.5)을 사용하면 표에 변화가 생겨도 연결 방법의 결정에 정확한 균형을 유지할 수 있다.마지막으로, 나는 나의 가상 CTE로 시작하지 않는 연결 경로를 제시하지 않았다. 왜냐하면, 나는 검색 계획기가 항상 거기서부터 시작하기를 원하기 때문이다. (값이나 제한 구조 때문에, 그것은 단지 한 줄만 알고 있기 때문이다.)
알림: 검색 기획사가 기수를 정확하게 예측할 수 없을 때, 알림은 일종의 변통 방법입니다. 통계 데이터가 표시할 수 없는 기수와 선택성을 이해하도록 도와주십시오.또한 CTE 추가는 다른 솔루션입니다.
Reference
이 문제에 관하여(pg hint 계획 및 단일 테이블 기준 수정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/yugabyte/pghintplan-and-single-table-cardinality-correction-3j45텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)