Զուգահեռ հարցումներ PostgreSQL-ում

Զուգահեռ հարցումներ PostgreSQL-ում
Ժամանակակից պրոցեսորներն ունեն շատ միջուկներ: Տարիներ շարունակ հավելվածները զուգահեռաբար հարցումներ են ուղարկում տվյալների բազաներ։ Եթե ​​դա աղյուսակի մի քանի տողերի վերաբերյալ հաշվետվության հարցում է, այն ավելի արագ է աշխատում մի քանի պրոցեսորներ օգտագործելիս, և PostgreSQL-ն կարողացել է դա անել 9.6 տարբերակից սկսած:

Զուգահեռ հարցման գործառույթի ներդրման համար պահանջվեց 3 տարի. մենք պետք է վերագրեինք կոդը հարցումների կատարման տարբեր փուլերում: PostgreSQL 9.6-ը ներկայացրեց ենթակառուցվածքը` կոդի հետագա բարելավման համար: Հետագա տարբերակներում զուգահեռաբար կատարվում են այլ տեսակի հարցումներ։

Սահմանափակումները

  • Մի միացրեք զուգահեռ կատարումը, եթե բոլոր միջուկներն արդեն զբաղված են, հակառակ դեպքում այլ հարցումները կդանդաղեն:
  • Ամենակարևորը, WORK_MEM բարձր արժեքներով զուգահեռ մշակումը մեծ քանակությամբ հիշողություն է օգտագործում. յուրաքանչյուր հեշ միացում կամ տեսակավորում վերցնում է work_mem հիշողությունը:
  • Ցածր հետաձգման OLTP հարցումները չեն կարող արագացվել զուգահեռ կատարմամբ: Եվ եթե հարցումը վերադարձնում է մեկ տող, զուգահեռ մշակումը միայն կդանդաղեցնի այն:
  • Մշակողները սիրում են օգտագործել TPC-H հենանիշը: Գուցե դուք ունեք նմանատիպ հարցումներ կատարյալ զուգահեռ կատարման համար:
  • Զուգահեռաբար կատարվում են միայն SELECT հարցումները՝ առանց պրեդիկատի կողպման:
  • Երբեմն ճիշտ ինդեքսավորումն ավելի լավ է, քան զուգահեռ ռեժիմով աղյուսակի հաջորդական սկանավորումը:
  • Հարցումների և կուրսորների դադարեցումը չի աջակցվում:
  • Պատուհանների ֆունկցիաները և պատվիրված հավաքածուի ագրեգատ ֆունկցիաները զուգահեռ չեն:
  • Դուք ոչինչ չեք շահում I/O ծանրաբեռնվածության մեջ:
  • Զուգահեռ տեսակավորման ալգորիթմներ չկան: Բայց տեսակավորումներով հարցումները որոշ առումներով կարող են իրականացվել զուգահեռ:
  • Փոխարինեք CTE-ն (WITH ...)-ով տեղադրված SELECT-ով՝ զուգահեռ մշակումը միացնելու համար:
  • Երրորդ կողմի տվյալների փաթաթանները դեռ չեն աջակցում զուգահեռ մշակմանը (բայց կարող էին):
  • FULL OUTER JOIN-ը չի աջակցվում:
  • max_rows-ն անջատում է զուգահեռ մշակումը:
  • Եթե ​​հարցումն ունի ֆունկցիա, որը նշված չէ Զուգահեռ ԱՆՎՏԱՆԳ, ապա այն կլինի միայնակ շղթայով:
  • SERIALIZABLE գործարքի մեկուսացման մակարդակը անջատում է զուգահեռ մշակումը:

Փորձարկման միջավայր

PostgreSQL մշակողները փորձել են նվազեցնել TPC-H հենանիշային հարցումների արձագանքման ժամանակը: Ներբեռնեք հենանիշը և հարմարեցնել այն PostgreSQL-ին. Սա TPC-H հենանիշի ոչ պաշտոնական օգտագործումն է՝ ոչ տվյալների բազայի կամ ապարատային համեմատության համար:

  1. Ներբեռնեք TPC-H_Tools_v2.17.3.zip (կամ ավելի նոր տարբերակ) TPC-ից դուրս.
  2. Վերանվանեք makefile.suite-ը Makefile-ի և փոխեք, ինչպես նկարագրված է այստեղ. https://github.com/tvondra/pg_tpch . Կազմեք կոդը make հրամանով։
  3. Ստեղծել տվյալներ. ./dbgen -s 10 ստեղծում է 23 ԳԲ տվյալների բազա: Սա բավական է զուգահեռ և ոչ զուգահեռ հարցումների կատարման տարբերությունը տեսնելու համար։
  4. Փոխարկել ֆայլերը tbl в csv с for и sed.
  5. Կլոնավորեք պահեստը pg_tpch և պատճենեք ֆայլերը csv в pg_tpch/dss/data.
  6. Ստեղծեք հարցումներ հրամանով qgen.
  7. Բեռնել տվյալները տվյալների բազայում հրամանով ./tpch.sh.

Զուգահեռ հաջորդական սկանավորում

Այն կարող է ավելի արագ լինել ոչ թե զուգահեռ ընթերցման պատճառով, այլ այն պատճառով, որ տվյալները տարածվում են բազմաթիվ պրոցեսորների միջուկներում: Ժամանակակից օպերացիոն համակարգերում PostgreSQL տվյալների ֆայլերը լավ են պահվում: Առաջ կարդալով, հնարավոր է պահեստից ավելի մեծ բլոկ ստանալ, քան PG daemon-ի պահանջները: Հետևաբար, հարցումների կատարումը չի սահմանափակվում սկավառակի I/O-ով: Այն սպառում է պրոցեսորի ցիկլերը՝

  • կարդալ տողերը մեկ առ մեկ աղյուսակի էջերից;
  • համեմատել լարային արժեքները և պայմանները WHERE.

Եկեք կատարենք պարզ հարցում select:

tpch=# explain analyze select l_quantity as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Seq Scan on lineitem (cost=0.00..1964772.00 rows=58856235 width=5) (actual time=0.014..16951.669 rows=58839715 loops=1)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 1146337
Planning Time: 0.203 ms
Execution Time: 19035.100 ms

Հերթական սկանավորումն առաջացնում է չափազանց շատ տողեր՝ առանց ագրեգացման, ուստի հարցումը կատարվում է մեկ պրոցեսորի միջուկով:

Եթե ​​ավելացնեք SUM(), կարող եք տեսնել, որ երկու աշխատանքային հոսքեր կօգնեն արագացնել հարցումը.

explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=1589702.14..1589702.15 rows=1 width=32) (actual time=8553.365..8553.365 rows=1 loops=1)
-> Gather (cost=1589701.91..1589702.12 rows=2 width=32) (actual time=8553.241..8555.067 rows=3 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)
-> Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 382112
Planning Time: 0.241 ms
Execution Time: 8555.131 ms

Զուգահեռ ագրեգացիա

Parallel Seq Scan հանգույցը արտադրում է տողեր մասնակի ագրեգացման համար: «Partial Aggregate» հանգույցը կտրում է այս տողերը՝ օգտագործելով SUM(). Վերջում յուրաքանչյուր աշխատանքային պրոցեսից SUM հաշվիչը հավաքվում է «Gather» հանգույցով:

Վերջնական արդյունքը հաշվարկվում է «Finalize Aggregate» հանգույցով: Եթե ​​դուք ունեք ձեր սեփական ագրեգացման գործառույթները, մի մոռացեք դրանք նշել որպես «զուգահեռ անվտանգ»:

Աշխատողների գործընթացների քանակը

Աշխատող գործընթացների թիվը կարող է ավելացվել առանց սերվերի վերագործարկման.

explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Finalize Aggregate (cost=1589702.14..1589702.15 rows=1 width=32) (actual time=8553.365..8553.365 rows=1 loops=1)
-> Gather (cost=1589701.91..1589702.12 rows=2 width=32) (actual time=8553.241..8555.067 rows=3 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)
-> Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)
Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 382112
Planning Time: 0.241 ms
Execution Time: 8555.131 ms

Ինչ է այստեղ կատարվում? Աշխատանքային գործընթացները եղել են 2 անգամ ավելի, և հարցումն արագացել է ընդամենը 1,6599 անգամ։ Հետաքրքիր են հաշվարկները։ Մենք ունեինք 2 աշխատանքային գործընթաց և 1 առաջնորդ։ Փոփոխությունից հետո դարձավ 4+1։

Զուգահեռ մշակման արդյունքում մեր առավելագույն արագացումը՝ 5/3 = 1,66 (6) անգամ:

Ինչպես է դա աշխատում.

Գործընթացները

Հարցման կատարումը միշտ սկսվում է առաջատար գործընթացից: Առաջնորդն ամեն ինչ անում է ոչ զուգահեռ և ինչ-որ զուգահեռ վերամշակում։ Մյուս գործընթացները, որոնք կատարում են նույն հարցումները, կոչվում են աշխատանքային գործընթացներ: Զուգահեռ մշակումն օգտագործում է ենթակառուցվածքը դինամիկ ֆոնային աշխատող գործընթացներ (9.4 տարբերակից): Քանի որ PostgreSQL-ի մյուս մասերն օգտագործում են ոչ թե թելեր, այլ գործընթացներ, 3 աշխատող գործընթացներով հարցումը կարող է 4 անգամ ավելի արագ լինել, քան ավանդական մշակումը:

Փոխազդեցություն

Աշխատող գործընթացները շփվում են ղեկավարի հետ հաղորդագրությունների հերթի միջոցով (հիմնված ընդհանուր հիշողության վրա): Յուրաքանչյուր գործընթաց ունի 2 հերթ՝ սխալների և բազմակի համար:

Քանի՞ աշխատանքային հոսք է անհրաժեշտ:

Նվազագույն սահմանաչափը նշված է պարամետրով max_parallel_workers_per_gather. Հարցման վազողն այնուհետև վերցնում է աշխատանքային գործընթացները պարամետրով սահմանափակված լողավազանից max_parallel_workers size. Վերջին սահմանափակումն է max_worker_processes, այսինքն՝ ֆոնային գործընթացների ընդհանուր թիվը։

Եթե ​​հնարավոր չի եղել տեղաբաշխել աշխատանքային գործընթաց, ապա վերամշակումը կլինի մեկ գործընթաց:

Հարցման պլանավորողը կարող է նվազեցնել աշխատանքային հոսքերը՝ կախված աղյուսակի կամ ինդեքսի չափից: Դրա համար կան պարամետրեր min_parallel_table_scan_size и min_parallel_index_scan_size.

set min_parallel_table_scan_size='8MB'
8MB table => 1 worker
24MB table => 2 workers
72MB table => 3 workers
x => log(x / min_parallel_table_scan_size) / log(3) + 1 worker

Ամեն անգամ, երբ սեղանը 3 անգամ մեծ է, քան min_parallel_(index|table)_scan_size, Postgres-ն ավելացնում է աշխատանքային գործընթաց։ Աշխատանքային հոսքերի քանակը հիմնված չէ ծախսերի վրա: Շրջանաձև կախվածությունը դժվարացնում է բարդ իրականացումները: Փոխարենը, պլանավորողն օգտագործում է պարզ կանոններ.

Գործնականում այս կանոնները միշտ չէ, որ հարմար են արտադրության համար, այնպես որ կարող եք փոխել աշխատանքային գործընթացների քանակը որոշակի աղյուսակի համար. ALTER TABLE ... SET (parallel_workers = N).

Ինչու՞ չի օգտագործվում զուգահեռ մշակումը:

Բացի սահմանափակումների երկար ցանկից, կան նաև ծախսերի ստուգումներ.

parallel_setup_cost - խուսափել կարճ հարցումների զուգահեռ մշակումից. Այս պարամետրը գնահատում է հիշողությունը պատրաստելու, գործընթացը սկսելու և նախնական տվյալների փոխանակման ժամանակը:

parallel_tuple_costՂեկավարի և աշխատողների միջև հաղորդակցությունը կարող է հետաձգվել աշխատանքային պրոցեսներից բազմակի քանակի համամասնությամբ: Այս պարամետրը հաշվարկում է տվյալների փոխանակման արժեքը:

Nested Loop Միացումներ

PostgreSQL 9.6+ может выполнять вложенные циклы параллельно — это простая операция.

explain (costs off) select c_custkey, count(o_orderkey)
                from    customer left outer join orders on
                                c_custkey = o_custkey and o_comment not like '%special%deposits%'
                group by c_custkey;
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Finalize GroupAggregate
   Group Key: customer.c_custkey
   ->  Gather Merge
         Workers Planned: 4
         ->  Partial GroupAggregate
               Group Key: customer.c_custkey
               ->  Nested Loop Left Join
                     ->  Parallel Index Only Scan using customer_pkey on customer
                     ->  Index Scan using idx_orders_custkey on orders
                           Index Cond: (customer.c_custkey = o_custkey)
                           Filter: ((o_comment)::text !~~ '%special%deposits%'::text)

Հավաքածուն տեղի է ունենում վերջին փուլում, ուստի Nested Loop Left Join-ը զուգահեռ գործողություն է: Parallel Index Only Scan-ը ներկայացվել է միայն 10-րդ տարբերակում: Այն աշխատում է զուգահեռ սերիական սկանավորման նման: Վիճակ c_custkey = o_custkey կարդում է մեկ պատվեր յուրաքանչյուր հաճախորդի տողի համար: Այնպես որ, դա զուգահեռ չէ:

Hash Միանալ

Յուրաքանչյուր աշխատող պրոցես ստեղծում է իր սեփական հեշ աղյուսակը մինչև PostgreSQL 11-ը: Եվ եթե այս գործընթացներից չորսից ավելին լինեն, կատարողականությունը չի բարելավվի: Նոր տարբերակում հեշ աղյուսակը համօգտագործվում է: Յուրաքանչյուր աշխատող գործընթաց կարող է օգտագործել WORK_MEM՝ հեշ աղյուսակ ստեղծելու համար:

select
        l_shipmode,
        sum(case
                when o_orderpriority = '1-URGENT'
                        or o_orderpriority = '2-HIGH'
                        then 1
                else 0
        end) as high_line_count,
        sum(case
                when o_orderpriority <> '1-URGENT'
                        and o_orderpriority <> '2-HIGH'
                        then 1
                else 0
        end) as low_line_count
from
        orders,
        lineitem
where
        o_orderkey = l_orderkey
        and l_shipmode in ('MAIL', 'AIR')
        and l_commitdate < l_receiptdate
        and l_shipdate < l_commitdate
        and l_receiptdate >= date '1996-01-01'
        and l_receiptdate < date '1996-01-01' + interval '1' year
group by
        l_shipmode
order by
        l_shipmode
LIMIT 1;
                                                                                                                                    QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=1964755.66..1964961.44 rows=1 width=27) (actual time=7579.592..7922.997 rows=1 loops=1)
   ->  Finalize GroupAggregate  (cost=1964755.66..1966196.11 rows=7 width=27) (actual time=7579.590..7579.591 rows=1 loops=1)
         Group Key: lineitem.l_shipmode
         ->  Gather Merge  (cost=1964755.66..1966195.83 rows=28 width=27) (actual time=7559.593..7922.319 rows=6 loops=1)
               Workers Planned: 4
               Workers Launched: 4
               ->  Partial GroupAggregate  (cost=1963755.61..1965192.44 rows=7 width=27) (actual time=7548.103..7564.592 rows=2 loops=5)
                     Group Key: lineitem.l_shipmode
                     ->  Sort  (cost=1963755.61..1963935.20 rows=71838 width=27) (actual time=7530.280..7539.688 rows=62519 loops=5)
                           Sort Key: lineitem.l_shipmode
                           Sort Method: external merge  Disk: 2304kB
                           Worker 0:  Sort Method: external merge  Disk: 2064kB
                           Worker 1:  Sort Method: external merge  Disk: 2384kB
                           Worker 2:  Sort Method: external merge  Disk: 2264kB
                           Worker 3:  Sort Method: external merge  Disk: 2336kB
                           ->  Parallel Hash Join  (cost=382571.01..1957960.99 rows=71838 width=27) (actual time=7036.917..7499.692 rows=62519 loops=5)
                                 Hash Cond: (lineitem.l_orderkey = orders.o_orderkey)
                                 ->  Parallel Seq Scan on lineitem  (cost=0.00..1552386.40 rows=71838 width=19) (actual time=0.583..4901.063 rows=62519 loops=5)
                                       Filter: ((l_shipmode = ANY ('{MAIL,AIR}'::bpchar[])) AND (l_commitdate < l_receiptdate) AND (l_shipdate < l_commitdate) AND (l_receiptdate >= '1996-01-01'::date) AND (l_receiptdate < '1997-01-01 00:00:00'::timestamp without time zone))
                                       Rows Removed by Filter: 11934691
                                 ->  Parallel Hash  (cost=313722.45..313722.45 rows=3750045 width=20) (actual time=2011.518..2011.518 rows=3000000 loops=5)
                                       Buckets: 65536  Batches: 256  Memory Usage: 3840kB
                                       ->  Parallel Seq Scan on orders  (cost=0.00..313722.45 rows=3750045 width=20) (actual time=0.029..995.948 rows=3000000 loops=5)
 Planning Time: 0.977 ms
 Execution Time: 7923.770 ms

TPC-H-ից 12 հարցումը հստակ ցույց է տալիս զուգահեռ հեշ կապը: Յուրաքանչյուր աշխատող գործընթաց նպաստում է ընդհանուր հեշ աղյուսակի ստեղծմանը:

Միավորել Միանալ

Միաձուլման միացումն իր բնույթով ոչ զուգահեռ է: Մի անհանգստացեք, եթե սա հարցման վերջին քայլն է, այն դեռ կարող է զուգահեռ աշխատել:

-- Query 2 from TPC-H
explain (costs off) select s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment
from    part, supplier, partsupp, nation, region
where
        p_partkey = ps_partkey
        and s_suppkey = ps_suppkey
        and p_size = 36
        and p_type like '%BRASS'
        and s_nationkey = n_nationkey
        and n_regionkey = r_regionkey
        and r_name = 'AMERICA'
        and ps_supplycost = (
                select
                        min(ps_supplycost)
                from    partsupp, supplier, nation, region
                where
                        p_partkey = ps_partkey
                        and s_suppkey = ps_suppkey
                        and s_nationkey = n_nationkey
                        and n_regionkey = r_regionkey
                        and r_name = 'AMERICA'
        )
order by s_acctbal desc, n_name, s_name, p_partkey
LIMIT 100;
                                                QUERY PLAN
----------------------------------------------------------------------------------------------------------
 Limit
   ->  Sort
         Sort Key: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey
         ->  Merge Join
               Merge Cond: (part.p_partkey = partsupp.ps_partkey)
               Join Filter: (partsupp.ps_supplycost = (SubPlan 1))
               ->  Gather Merge
                     Workers Planned: 4
                     ->  Parallel Index Scan using <strong>part_pkey</strong> on part
                           Filter: (((p_type)::text ~~ '%BRASS'::text) AND (p_size = 36))
               ->  Materialize
                     ->  Sort
                           Sort Key: partsupp.ps_partkey
                           ->  Nested Loop
                                 ->  Nested Loop
                                       Join Filter: (nation.n_regionkey = region.r_regionkey)
                                       ->  Seq Scan on region
                                             Filter: (r_name = 'AMERICA'::bpchar)
                                       ->  Hash Join
                                             Hash Cond: (supplier.s_nationkey = nation.n_nationkey)
                                             ->  Seq Scan on supplier
                                             ->  Hash
                                                   ->  Seq Scan on nation
                                 ->  Index Scan using idx_partsupp_suppkey on partsupp
                                       Index Cond: (ps_suppkey = supplier.s_suppkey)
               SubPlan 1
                 ->  Aggregate
                       ->  Nested Loop
                             Join Filter: (nation_1.n_regionkey = region_1.r_regionkey)
                             ->  Seq Scan on region region_1
                                   Filter: (r_name = 'AMERICA'::bpchar)
                             ->  Nested Loop
                                   ->  Nested Loop
                                         ->  Index Scan using idx_partsupp_partkey on partsupp partsupp_1
                                               Index Cond: (part.p_partkey = ps_partkey)
                                         ->  Index Scan using supplier_pkey on supplier supplier_1
                                               Index Cond: (s_suppkey = partsupp_1.ps_suppkey)
                                   ->  Index Scan using nation_pkey on nation nation_1
                                         Index Cond: (n_nationkey = supplier_1.s_nationkey)

«Merge Join» հանգույցը գտնվում է «Gather Merge»-ի վերեւում: Այսպիսով, միաձուլումը չի օգտագործում զուգահեռ մշակում: Բայց «Զուգահեռ ինդեքսի սկանավորում» հանգույցը դեռ օգնում է հատվածին part_pkey.

Միացում ըստ բաժինների

PostgreSQL 11-ում միացում ըստ բաժինների լռելյայն անջատված է. այն ունի շատ թանկ պլանավորում: Նմանատիպ բաժանումներով աղյուսակները կարելի է միացնել բաժանում առ բաժան: Այս կերպ Postgres-ը կօգտագործի ավելի փոքր հեշ աղյուսակներ: Բաժինների յուրաքանչյուր կապ կարող է լինել զուգահեռ:

tpch=# set enable_partitionwise_join=t;
tpch=# explain (costs off) select * from prt1 t1, prt2 t2
where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
                    QUERY PLAN
---------------------------------------------------
 Append
   ->  Hash Join
         Hash Cond: (t2.b = t1.a)
         ->  Seq Scan on prt2_p1 t2
               Filter: ((b >= 0) AND (b <= 10000))
         ->  Hash
               ->  Seq Scan on prt1_p1 t1
                     Filter: (b = 0)
   ->  Hash Join
         Hash Cond: (t2_1.b = t1_1.a)
         ->  Seq Scan on prt2_p2 t2_1
               Filter: ((b >= 0) AND (b <= 10000))
         ->  Hash
               ->  Seq Scan on prt1_p2 t1_1
                     Filter: (b = 0)
tpch=# set parallel_setup_cost = 1;
tpch=# set parallel_tuple_cost = 0.01;
tpch=# explain (costs off) select * from prt1 t1, prt2 t2
where t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;
                        QUERY PLAN
-----------------------------------------------------------
 Gather
   Workers Planned: 4
   ->  Parallel Append
         ->  Parallel Hash Join
               Hash Cond: (t2_1.b = t1_1.a)
               ->  Parallel Seq Scan on prt2_p2 t2_1
                     Filter: ((b >= 0) AND (b <= 10000))
               ->  Parallel Hash
                     ->  Parallel Seq Scan on prt1_p2 t1_1
                           Filter: (b = 0)
         ->  Parallel Hash Join
               Hash Cond: (t2.b = t1.a)
               ->  Parallel Seq Scan on prt2_p1 t2
                     Filter: ((b >= 0) AND (b <= 10000))
               ->  Parallel Hash
                     ->  Parallel Seq Scan on prt1_p1 t1
                           Filter: (b = 0)

Հիմնական բանը այն է, որ հատվածներում կապը զուգահեռ է միայն այն դեպքում, եթե այդ հատվածները բավականաչափ մեծ են:

Զուգահեռ հավելված

Զուգահեռ հավելված կարող է օգտագործվել տարբեր բլոկների փոխարեն տարբեր աշխատանքային հոսքերում: Սա սովորաբար տեղի է ունենում UNION ALL հարցումների դեպքում: Թերությունը պակաս զուգահեռականությունն է, քանի որ յուրաքանչյուր աշխատողի պրոցեսը մշակում է միայն 1 հարցում:

Այստեղ գործում է 2 աշխատանքային գործընթաց, թեև 4-ը միացված է:

tpch=# explain (costs off) select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '1998-12-01' - interval '105' day union all select sum(l_quantity) as sum_qty from lineitem where l_shipdate <= date '2000-12-01' - interval '105' day;
                                           QUERY PLAN
------------------------------------------------------------------------------------------------
 Gather
   Workers Planned: 2
   ->  Parallel Append
         ->  Aggregate
               ->  Seq Scan on lineitem
                     Filter: (l_shipdate <= '2000-08-18 00:00:00'::timestamp without time zone)
         ->  Aggregate
               ->  Seq Scan on lineitem lineitem_1
                     Filter: (l_shipdate <= '1998-08-18 00:00:00'::timestamp without time zone)

Ամենակարևոր փոփոխականները

  • WORK_MEM-ը սահմանափակում է հիշողությունը յուրաքանչյուր գործընթացի համար, ոչ միայն հարցումների համար՝ work_mem գործընթացները կապեր = շատ հիշողություն:
  • max_parallel_workers_per_gather - քանի աշխատող գործընթաց կօգտագործի կատարող ծրագիրը պլանից զուգահեռ մշակման համար:
  • max_worker_processes — կարգավորում է աշխատանքային պրոցեսների ընդհանուր թիվը սերվերի վրա պրոցեսորի միջուկների թվին:
  • max_parallel_workers - նույնը, բայց զուգահեռ աշխատանքային գործընթացների համար:

Արդյունքները

9.6 տարբերակի դրությամբ զուգահեռ մշակումը կարող է զգալիորեն բարելավել բարդ հարցումների աշխատանքը, որոնք սկանավորում են բազմաթիվ տողեր կամ ինդեքսներ: PostgreSQL 10-ում զուգահեռ մշակումը լռելյայն միացված է: Հիշեք, որ այն անջատեք մեծ OLTP ծանրաբեռնված սերվերների վրա: Հերթական սկանավորումները կամ ինդեքսային սկանավորումները մեծ քանակությամբ ռեսուրսներ են սպառում: Եթե ​​դուք չեք վարում հաշվետվություն ամբողջ տվյալների վերաբերյալ, կարող եք բարելավել հարցումների կատարողականը` պարզապես ավելացնելով բացակայող ինդեքսները կամ օգտագործելով պատշաճ բաժանում:

Սայլակ

Source: www.habr.com

Добавить комментарий