{"id":30900,"date":"2019-10-31T21:38:02","date_gmt":"2019-10-31T18:38:02","guid":{"rendered":"https:\/\/prohoster.info\/blog\/parallelnye-zaprosy-v-postgresql\/"},"modified":"2019-10-31T21:38:02","modified_gmt":"2019-10-31T18:38:02","slug":"parallelnye-zaprosy-v-postgresql","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","title":{"rendered":"Paraleln\u00e9 po\u017eiadavky v PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Paraleln\u00e9 po\u017eiadavky v PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/04\/bbb4b4d3f8714bbdb9b26ada2f2253b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nV modern\u00fdch CPU je ve\u013ea jadier. Rony sa aplik\u00e1cie zasielali po\u017eiadavky na datab\u00e1zy paralelne. Ak ide o reportov\u00fa po\u017eiadavku na mno\u017estvo riadkov v tabu\u013eke, vykon\u00e1 sa r\u00fdchlej\u0161ie, ke\u010f s\u00fa zapojen\u00e9 viacer\u00e9 CPU, a v PostgreSQL je to mo\u017en\u00e9 od verzie 9.6.<\/p>\n<p><\/p>\n<p>Trvalo 3 roky, aby sa implementovala funkcia paraleln\u00fdch po\u017eiadaviek \u2014 museli sme prep\u00edsa\u0165 k\u00f3d v r\u00f4znych f\u00e1zach vykon\u00e1vania po\u017eiadaviek. V PostgreSQL 9.6 sa objavila infra\u0161trukt\u00fara pre \u010fal\u0161ie zlep\u0161enie k\u00f3du. V nasleduj\u00facich verzi\u00e1ch sa aj in\u00e9 typy po\u017eiadaviek vykon\u00e1vaj\u00fa paralelne.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"ogranicheniya\">Obmedzenia<\/h3>\n<p><\/p>\n<ul>\n<li>Nezapojujte paraleln\u00e9 spracovanie, ak s\u00fa v\u0161etky jadr\u00e1 u\u017e obsaden\u00e9, inak bud\u00fa ostatn\u00e9 po\u017eiadavky spoma\u013eova\u0165.<\/li>\n<li>Najd\u00f4le\u017eitej\u0161ie je, \u017ee paraleln\u00e9 spracovanie s vysok\u00fdmi hodnotami WORK_MEM pou\u017eije ve\u013ea pam\u00e4te \u2014 ka\u017ed\u00e9 ha\u0161ovanie alebo triedenie zaber\u00e1 pam\u00e4\u0165 v objeme work_mem.<\/li>\n<li>OLTP po\u017eiadavky s n\u00edzkou latenciou nemo\u017eno ur\u00fdchli\u0165 paraleln\u00fdm vykon\u00e1van\u00edm. A ak po\u017eiadavka vracia jeden riadok, paraleln\u00e9 spracovanie ju iba spomal\u00ed.<\/li>\n<li>Developeri radi pou\u017e\u00edvaj\u00fa benchmark TPC-H. Mo\u017eno m\u00e1te podobn\u00e9 po\u017eiadavky na ide\u00e1lne paraleln\u00e9 spracovanie.<\/li>\n<li>Iba SELECT po\u017eiadavky bez predik\u00e1tneho uzamknutia s\u00fa vykon\u00e1van\u00e9 paralelne.<\/li>\n<li>Niekedy je spr\u00e1vna index\u00e1cia lep\u0161ia ako sekven\u010dn\u00e9 skenovanie tabu\u013eky v paralelnom re\u017eime.<\/li>\n<li>Pozastavenie po\u017eiadaviek a kurzory nie s\u00fa podporovan\u00e9.<\/li>\n<li>Okno a agreg\u00e1tne funkcie usporiadan\u00fdch mno\u017e\u00edn nie s\u00fa paraleln\u00e9.<\/li>\n<li>V pracovnej z\u00e1\u0165a\u017ei vstup-nozadu ni\u010d nez\u00edskavate.<\/li>\n<li>Paraleln\u00e9 algoritmy triedenia neexistuj\u00fa. Ale po\u017eiadavky s trieden\u00edm m\u00f4\u017eu by\u0165 vykon\u00e1van\u00e9 paralelne v niektor\u00fdch aspektoch.<\/li>\n<li>Nahra\u010fte CTE (WITH \u2026) vnoren\u00fdm SELECT, aby ste zapojili paraleln\u00e9 spracovanie.<\/li>\n<li>Obaly extern\u00fdch d\u00e1t zatia\u013e nepodporuj\u00fa paraleln\u00e9 spracovanie (a mohli by!).<\/li>\n<li>FULL OUTER JOIN nie je podporovan\u00fd.<\/li>\n<li>max_rows zakazuje paraleln\u00e9 spracovanie.<\/li>\n<li>Ak je vo va\u0161ej po\u017eiadavke funkcia, ktor\u00e1 nie je ozna\u010den\u00e1 ako PARALLEL SAFE, bude jednoprvkov\u00e1.<\/li>\n<li>\u00darove\u0148 izol\u00e1cie transakcie SERIALIZABLE zakazuje paraleln\u00e9 spracovanie.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"testovaya-sreda\">Testovacia environ<\/h3>\n<p><\/p>\n<p>Developeri PostgreSQL sa sna\u017eili skr\u00e1ti\u0165 \u010das odozvy po\u017eiadaviek benchmarku TPC-H. Stiahnite si benchmark a <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">prisp\u00f4sobte ho PostgreSQL<\/a><\/noindex>. Toto nie je ofici\u00e1lne pou\u017eitie benchmarku TPC-H \u2014 nie je na porovn\u00e1vanie datab\u00e1z alebo hardv\u00e9ru.<\/p>\n<p><\/p>\n<ol>\n<li>Stiahnite TPC-H_Tools_v2.17.3.zip (alebo nov\u0161iu verziu) <noindex><a rel=\"nofollow\" href=\"http:\/\/www.tpc.org\/tpc_documents_current_versions\/current_specifications.asp\">z ofici\u00e1lnej str\u00e1nky TPC<\/a><\/noindex>.<\/li>\n<li>Premenova\u0165 makefile.suite na Makefile a zmeni\u0165, ako je uveden\u00e9 tu: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">https:\/\/github.com\/tvondra\/pg_tpch <\/a><\/noindex>. Skontrolujte k\u00f3d pr\u00edkazom make.<\/li>\n<li>Generujte d\u00e1ta: <code>.\/dbgen -s 10<\/code> vytvor\u00ed datab\u00e1zu s kapacitou 23 GB. To bude sta\u010di\u0165, aby ste videli rozdiel v v\u00fdkonnosti paraleln\u00fdch a neparaleln\u00fdch dotazov.<\/li>\n<li>Konvertujte s\u00fabory <code>tbl<\/code> v <code>csv s for<\/code> a <code>sed<\/code>.<\/li>\n<li>Klonujte repozit\u00e1r <code>pg_tpch<\/code> a skop\u00edrujte s\u00fabory <code>csv<\/code> v <code>pg_tpch\/dss\/data<\/code>.<\/li>\n<li>Vytvorte dotazy pr\u00edkazom <code>qgen<\/code>.<\/li>\n<li>Na\u010d\u00edtajte d\u00e1ta do datab\u00e1zy pr\u00edkazom <code>.\/tpch.sh<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"parallelnoe-posledovatelnoe-skanirovanie\">Paraleln\u00e9 sekven\u010dn\u00e9 skenovanie<\/h3>\n<p><\/p>\n<p>M\u00f4\u017ee by\u0165 r\u00fdchlej\u0161ie nie kv\u00f4li paraleln\u00e9mu \u010d\u00edtaniu, ale preto, \u017ee d\u00e1ta s\u00fa rozlo\u017een\u00e9 na viacer\u00fdch CPU jadr\u00e1ch. V modern\u00fdch OS s\u00fa s\u00fabory d\u00e1t PostgreSQL dobre cache-ovan\u00e9. S predv\u00eddav\u00fdm \u010d\u00edtan\u00edm m\u00f4\u017eete z \u00falo\u017eiska z\u00edska\u0165 viac blokov, ako po\u017eaduje d\u00e9mon PG. Preto nie je v\u00fdkon dotazu obmedzen\u00fd I\/O disku. Spotreb\u00fava to cykly CPU na:<\/p>\n<p><\/p>\n<ul>\n<li>\u010d\u00edtanie riadkov jeden po druhom zo str\u00e1n tabu\u013eky;<\/li>\n<li>porovn\u00e1vanie hodn\u00f4t riadkov a podmienok <code>WHERE<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>Vykonajme jednoduch\u00fd dotaz <code>select<\/code>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">tpch=# explain analyze select l_quantity as sum_qty from lineitem where l_shipdate &lt;=&#039;1998-12-01&#039; - interval &#039;105&#039; day;\nQUERY PLAN\n--------------------------------------------------------------------------------------------------------------------------\nSeq Scan on lineitem (cost=0.00..1964772.00 rows=58856235 width=5) (akt. \u010das=0.014..16951.669 riadkov=58839715 slu\u010diek=1)\nFilter: (l_shipdate &lt;=&#039;1998-08-18 00:00:00&#039;::timestamp bez \u010dasovej z\u00f3ny)\nRiadky odstr\u00e1nen\u00e9 filtrom: 1146337\n\u010cas pl\u00e1novania: 0.203 ms\n\u010cas vykonania: 19035.100 ms<\/code><\/pre>\n<p><\/p>\n<p>Sekven\u010dn\u00e9 skenovanie poskytuje pr\u00edli\u0161 ve\u013ea riadkov bez agreg\u00e1cie, tak\u017ee dotaz sa vykon\u00e1va jedn\u00fdm CPU jadrom.<\/p>\n<p><\/p>\n<p>Ak prid\u00e1me <code>SUM()<\/code>, je vidie\u0165, \u017ee dva pracovn\u00e9 procesy pom\u00f4\u017eu ur\u00fdchli\u0165 dotaz:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate  Gather (cost=1589701.91..1589702.12 rows=2 width=32) (akt. \u010das=8553.241..8555.067 riadkov=3 slu\u010diek=1)\nNapl\u00e1novan\u00ed pracovn\u00edci: 2\nSpusten\u00e9 pracovn\u00edci: 2\n-&gt; Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (akt. \u010das=8547.546..8547.546 riadkov=1 slu\u010diek=3)\n-&gt; Paraleln\u00e9 sekven\u010dn\u00e9 skenovanie na lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (akt. \u010das=0.038..5998.417 riadkov=19613238 slu\u010diek=3)\nFilter: (l_shipdate &lt;=&#039;1998-08-18 00:00:00&#039;::timestamp bez \u010dasovej z\u00f3ny)\nRiadky odstr\u00e1nen\u00e9 filtrom: 382112\n\u010cas pl\u00e1novania: 0.241 ms\n\u010cas vykonania: 8555.131 ms<\/code><\/pre>\n<p><\/p>\n<h3 id=\"parallelnaya-agregaciya\">Paraleln\u00e1 agreg\u00e1cia<\/h3>\n<p><\/p>\n<p>N\u00f3da \u00abParallel Seq Scan\u00bb generuje riadky pre \u010diasto\u010dn\u00fa agreg\u00e1ciu. N\u00f3da \u00abPartial Aggregate\u00bb skracuje tieto riadky pomocou <code>SUM()<\/code>. Na konci sa \u010d\u00edta\u010d SUM z ka\u017ed\u00e9ho pracovn\u00e9ho procesu zhroma\u017e\u010fuje n\u00f3dou \u00abGather\u00bb.<\/p>\n<p><\/p>\n<p>Kone\u010dn\u00fd v\u00fdsledok sa vypo\u010d\u00edtava n\u00f3dou \u00abFinalize Aggregate\u00bb. Ak m\u00e1te vlastn\u00e9 agrega\u010dn\u00e9 funkcie, nezabudnite ich ozna\u010di\u0165 ako \u00abparallel safe\u00bb.<\/p>\n<p><\/p>\n<h3 id=\"kolichestvo-rabochih-processov\">Po\u010det pracovn\u00fdch procesov<\/h3>\n<p><\/p>\n<p>Po\u010det pracovn\u00fdch procesov je mo\u017en\u00e9 zv\u00fd\u0161i\u0165 bez re\u0161tartovania servera:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">explain analyze select sum(l_quantity) as sum_qty from lineitem where l_shipdate  Gather (cost=1589701.91..1589702.12 rows=2 width=32) (akt. \u010das=8553.241..8555.067 riadkov=3 slu\u010diek=1)\nNapl\u00e1novan\u00ed pracovn\u00edci: 2\nSpusten\u00e9 pracovn\u00edci: 2\n-&gt; Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (akt. \u010das=8547.546..8547.546 riadkov=1 slu\u010diek=3)\n-&gt; Paraleln\u00e9 sekven\u010dn\u00e9 skenovanie na lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (akt. \u010das=0.038..5998.417 riadkov=19613238 slu\u010diek=3)\nFilter: (l_shipdate &lt;=&#039;1998-08-18 00:00:00&#039;::timestamp bez \u010dasovej z\u00f3ny)\nRiadky odstr\u00e1nen\u00e9 filtrom: 382112\n\u010cas pl\u00e1novania: 0.241 ms\n\u010cas vykonania: 8555.131 ms<\/code><\/pre>\n<p><\/p>\n<p>\u010co sa tu deje? Po\u010det procesov sa zv\u00fd\u0161il dvojn\u00e1sobne a dopyt sa stal len 1,6599-kr\u00e1t r\u00fdchlej\u0161\u00edm. V\u00fdpo\u010dty s\u00fa zauj\u00edmav\u00e9. Mali sme 2 pracovn\u00e9 procesy a 1 l\u00eddra. Po zmene sa to zmenilo na 4+1.<\/p>\n<p><\/p>\n<p>Na\u0161e maxim\u00e1lne zr\u00fdchlenie v\u010faka paraleln\u00e9mu spracovaniu: 5\/3 = 1,66(6) kr\u00e1t.<\/p>\n<p><\/p>\n<h2 id=\"kak-eto-rabotaet\">Ako to funguje?<\/h2>\n<p><\/p>\n<h3 id=\"processy\">Procesy<\/h3>\n<p><\/p>\n<p>Vykonanie dopytu v\u017edy za\u010d\u00edna od ved\u00faceho procesu. L\u00eddrova rob\u00ed v\u0161etku nepren\u00e1\u0161ate\u013en\u00fa a \u010das\u0165 prenosnej pr\u00e1ce. Ostatn\u00e9 procesy, ktor\u00e9 vykon\u00e1vaj\u00fa rovnak\u00e9 dopyty, sa naz\u00fdvaj\u00fa pracovn\u00e9 procesy. Paraleln\u00e9 spracovanie vyu\u017e\u00edva infra\u0161trukt\u00faru <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/bgworker.html\">dynamick\u00fdch pozad\u00ed pracovn\u00fdch procesov<\/a><\/noindex> (od verzie 9.4). Ke\u010f\u017ee in\u00e9 \u010dasti PostgreSQL pou\u017e\u00edvaj\u00fa procesy a nie vl\u00e1kna, dopyt s 3 pracovn\u00fdmi procesmi mohol by\u0165 4-kr\u00e1t r\u00fdchlej\u0161\u00ed ako tradi\u010dn\u00e9 spracovanie.<\/p>\n<p><\/p>\n<h3 id=\"vzaimodeystvie\">Interakcia<\/h3>\n<p><\/p>\n<p>Pracovn\u00e9 procesy komunikuj\u00fa s l\u00eddrom prostredn\u00edctvom fronty spr\u00e1v (na b\u00e1ze zdie\u013eanej pam\u00e4te). Ka\u017ed\u00fd proces m\u00e1 2 fronty: na chyby a na tuple.<\/p>\n<p><\/p>\n<h3 id=\"skolko-nuzhno-rabochih-processov\">Ko\u013eko pracovn\u00fdch procesov je potrebn\u00fdch?<\/h3>\n<p><\/p>\n<p>Minim\u00e1lne obmedzenie je stanoven\u00e9 parametrom <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER\"><code>max_parallel_workers_per_gather<\/code><\/a><\/noindex>. Potom vykon\u00e1vate\u013e dopytov berie pracovn\u00e9 procesy z poolu, obmedzen\u00e9ho parametrom <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES\"><code>max_parallel_workers size<\/code><\/a><\/noindex>. Posledn\u00e9 obmedzenie je <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES\"><code>max_worker_processes<\/code><\/a><\/noindex>, teda celkov\u00fd po\u010det pozad\u00ed procesov.<\/p>\n<p><\/p>\n<p>Ak sa nepodar\u00ed z\u00edska\u0165 pracovn\u00fd proces, spracovanie bude jednoprosesorov\u00e9.<\/p>\n<p><\/p>\n<p>Planner dopytov m\u00f4\u017ee skr\u00e1ti\u0165 pracovn\u00e9 procesy v z\u00e1vislosti od ve\u013ekosti tabu\u013eky alebo indexu. Na to existuj\u00fa parametre <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-MIN-PARALLEL-TABLE-SCAN-SIZE\"><code>min_parallel_table_scan_size<\/code><\/a><\/noindex> a <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-MIN-PARALLEL-INDEX-SCAN-SIZE\"><code>min_parallel_index_scan_size<\/code><\/a><\/noindex>.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">set min_parallel_table_scan_size='8MB'\n8MB tabu\u013eka =&gt; 1 pracovn\u00edk\n24MB tabu\u013eka =&gt; 2 pracovn\u00edci\n72MB tabu\u013eka =&gt; 3 pracovn\u00edci\nx =&gt; log(x \/ min_parallel_table_scan_size) \/ log(3) + 1 pracovn\u00edk<\/code><\/pre>\n<p><\/p>\n<p>Ka\u017ed\u00fdkr\u00e1t, ke\u010f je tabu\u013eka 3-kr\u00e1t v\u00e4\u010d\u0161ia ako <code>min_parallel_(index|table)_scan_size<\/code>, Postgres prid\u00e1 pracovn\u00fd proces. Po\u010det pracovn\u00fdch procesov nie je zalo\u017een\u00fd na n\u00e1kladoch. Cyklick\u00e9 z\u00e1vislosti komplikuj\u00fa zlo\u017eit\u00fa implement\u00e1ciu. Namiesto toho sa planner riadi jednoduch\u00fdmi pravidlami.<\/p>\n<p><\/p>\n<p>V praxi tieto pravidl\u00e1 nie s\u00fa v\u017edy vhodn\u00e9 pre produkciu, tak\u017ee je mo\u017en\u00e9 zmeni\u0165 po\u010det pracovn\u00fdch procesov pre konkr\u00e9tnu tabu\u013eku: ALTER TABLE \u2026 SET (<code>parallel_workers = N<\/code>).<\/p>\n<p><\/p>\n<h3 id=\"pochemu-parallelnaya-obrabotka-ne-ispolzuetsya\">Pre\u010do sa paraleln\u00e9 spracovanie nepou\u017e\u00edva?<\/h3>\n<p><\/p>\n<p>Okrem dlh\u00e9ho zoznamu obmedzen\u00ed s\u00fa tu aj kontroly n\u00e1kladov:<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-PARALLEL-SETUP-COST\"><code>parallel_setup_cost<\/code><\/a><\/noindex> \u2014 aby sa predi\u0161lo paraleln\u00e9mu spracovaniu kr\u00e1tkych dopytov. Tento parametre odhaduje \u010das na pr\u00edpravu pam\u00e4te, spustenie procesu a po\u010diato\u010dn\u00fa v\u00fdmenu \u00fadajov.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/runtime-config-query.html#GUC-PARALLEL-TUPLE-COST\"><code>parallel_tuple_cost<\/code><\/a><\/noindex>: komunik\u00e1cia l\u00eddra s pracovn\u00edkmi m\u00f4\u017ee trva\u0165 \u00famerne k po\u010dtu k\u00f4p od pracovn\u00fdch procesov. Tento parameter po\u010d\u00edta n\u00e1klady na v\u00fdmenu \u00fadajov.<\/p>\n<p><\/p>\n<h3 id=\"soedineniya-vlozhennyh-ciklov--nested-loop-join\">Spojenia vnoren\u00fdch cyklov \u2014 Nested Loop Join<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">PostgreSQL 9.6+ m\u00f4\u017ee vykon\u00e1va\u0165 vnoren\u00e9 cykly paralelne \u2014 to je jednoduch\u00e1 oper\u00e1cia.<br><br>explain (costs off) select c_custkey, count(o_orderkey)<br> from customer left outer join orders on<br> c_custkey = o_custkey and o_comment not like '%specialposits%'<br> group by c_custkey;<br> QUERY PLAN<br>--------------------------------------------------------------------------------------<br> Finalize GroupAggregate<br> Group Key: customer.c_custkey<br> -&gt; Gather Merge<br> Workers Planned: 4<br> -&gt; Partial GroupAggregate<br> Group Key: customer.c_custkey<br> -&gt; Nested Loop Left Join<br> -&gt; Parallel Index Only Scan using customer_pkey on customer<br> -&gt; Index Scan using idx_orders_custkey on orders<br> Index Cond: (customer.c_custkey = o_custkey)<br> Filter: ((o_comment)::text !~~ '%specialposits%'::text)<\/code><\/pre>\n<p><\/p>\n<p>Zber sa uskuto\u010d\u0148uje na poslednom kroku, tak\u017ee Nested Loop Left Join \u2014 je to paraleln\u00e1 oper\u00e1cia. Parallel Index Only Scan sa objavil a\u017e vo verzii 10. Funguje podobne ako paraleln\u00e9 sekven\u010dn\u00e9 skenovanie. Podmienka <code>c_custkey = o_custkey<\/code> \u010d\u00edtal jeden poriadok pre ka\u017ed\u00fd riadok z\u00e1kazn\u00edka. Tak\u017ee nie je paraleln\u00fd.<\/p>\n<p><\/p>\n<h3 id=\"hesh-soedinenie--hash-join\">Hash Join \u2014 Hash Join<\/h3>\n<p><\/p>\n<p>Ka\u017ed\u00fd pracovn\u00fd proces vytv\u00e1ra svoju hash tabu\u013eku do PostgreSQL 11. A ak je t\u00fdchto procesov viac ako \u0161tyri, v\u00fdkon sa nezv\u00fd\u0161i. V novej verzii je hash tabu\u013eka spolo\u010dn\u00e1. Ka\u017ed\u00fd pracovn\u00fd proces m\u00f4\u017ee vyu\u017ei\u0165 WORK_MEM na vytvorenie hash tabu\u013eky.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">vyber\n        l_shipmode,\n        s\u00fa\u010det(pr\u00edpad\n                ke\u010f o_orderpriority = '1-URGENT'\n                        alebo o_orderpriority = '2-HIGH'\n                        potom 1\n                inak 0\n        koniec) ako high_line_count,\n        s\u00fa\u010det(pr\u00edpad\n                ke\u010f o_orderpriority  '1-URGENT'\n                        a o_orderpriority  '2-HIGH'\n                        potom 1\n                inak 0\n        koniec) ako low_line_count\nz\n        orders,\n        lineitem\nkde\n        o_orderkey = l_orderkey\n        a l_shipmode v ('MAIL', 'AIR')\n        a l_commitdate &lt; l_receiptdate\n        a l_shipdate = d\u00e1tum '1996-01-01'\n        a l_receiptdate &lt; d\u00e1tum &#039;1996-01-01&#039; + interval &#039;1&#039; rok\ngrupova\u0165 pod\u013ea\n        l_shipmode\nporadie pod\u013ea\n        l_shipmode\nLIMIT 1;\n                                                                                                                                    PL\u00c1N DOTAZU\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n Limit  (n\u00e1klady=1964755.66..1964961.44 riadkov=1 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7579.592..7922.997 riadkov=1 smy\u010diek=1)\n   -&gt;  Finalizova\u0165 GroupAggregate  (n\u00e1klady=1964755.66..1966196.11 riadkov=7 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7579.590..7579.591 riadkov=1 smy\u010diek=1)\n         Skupinov\u00fd k\u013e\u00fa\u010d: lineitem.l_shipmode\n         -&gt;  Zbieranie zl\u00fa\u010den\u00edm  (n\u00e1klady=1964755.66..1966195.83 riadkov=28 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7559.593..7922.319 riadkov=6 smy\u010diek=1)\n               Zamestnanci pl\u00e1novan\u00ed: 4\n               Zamestnanci na\u0161tartovan\u00ed: 4\n               -&gt;  \u010ciasto\u010dn\u00fd GroupAggregate  (n\u00e1klady=1963755.61..1965192.44 riadkov=7 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7548.103..7564.592 riadkov=2 smy\u010diek=5)\n                     Skupinov\u00fd k\u013e\u00fa\u010d: lineitem.l_shipmode\n                     -&gt;  Triedenie  (n\u00e1klady=1963755.61..1963935.20 riadkov=71838 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7530.280..7539.688 riadkov=62519 smy\u010diek=5)\n                           K\u013e\u00fa\u010d triedenia: lineitem.l_shipmode\n                           Met\u00f3da triedenia: extern\u00e9 zl\u00fa\u010denie  Disk: 2304kB\n                           Zamestnanec 0:  Met\u00f3da triedenia: extern\u00e9 zl\u00fa\u010denie  Disk: 2064kB\n                           Zamestnanec 1:  Met\u00f3da triedenia: extern\u00e9 zl\u00fa\u010denie  Disk: 2384kB\n                           Zamestnanec 2:  Met\u00f3da triedenia: extern\u00e9 zl\u00fa\u010denie  Disk: 2264kB\n                           Zamestnanec 3:  Met\u00f3da triedenia: extern\u00e9 zl\u00fa\u010denie  Disk: 2336kB\n                           -&gt;  Paraleln\u00fd hash join  (n\u00e1klady=382571.01..1957960.99 riadkov=71838 \u0161\u00edrka=27) (skuto\u010dn\u00fd \u010das=7036.917..7499.692 riadkov=62519 smy\u010diek=5)\n                                 Hash Cond: (lineitem.l_orderkey = orders.o_orderkey)\n                                 -&gt;  Paraleln\u00e9 sekven\u010dn\u00e9 skenovanie na lineitem  (n\u00e1klady=0.00..1552386.40 riadkov=71838 \u0161\u00edrka=19) (skuto\u010dn\u00fd \u010das=0.583..4901.063 riadkov=62519 smy\u010diek=5)\n                                       Filter: ((l_shipmode = \u013dUBOVOLN\u00c9 (&#039;{MAIL,AIR}&#039;::bpchar[])) A (l_commitdate &lt; l_receiptdate) A (l_shipdate = '1996-01-01'::d\u00e1tum) A (l_receiptdate &lt; &#039;1997-01-01 00:00:00&#039;::timestamp bez \u010dasovej z\u00f3ny))\n                                       Riadky odstr\u00e1nen\u00e9 filtrom: 11934691\n                                 -&gt;  Paraleln\u00fd hash  (n\u00e1klady=313722.45..313722.45 riadkov=3750045 \u0161\u00edrka=20) (skuto\u010dn\u00fd \u010das=2011.518..2011.518 riadkov=3000000 smy\u010diek=5)\n                                       Pam\u00e4\u0165ov\u00e9 pou\u017eitie: 3840kB\n                                       -&gt;  Paraleln\u00e9 sekven\u010dn\u00e9 skenovanie na orders  (n\u00e1klady=0.00..313722.45 riadkov=3750045 \u0161\u00edrka=20) (skuto\u010dn\u00fd \u010das=0.029..995.948 riadkov=3000000 smy\u010diek=5)\n \u010cas pl\u00e1novania: 0.977 ms\n \u010cas vykon\u00e1vania: 7923.770 ms<\/code><\/pre>\n<p><\/p>\n<p>Dotaz 12 z TPC-H ukazuje paraleln\u00e9 hash pripojenie. Ka\u017ed\u00fd pracovn\u00fd proces sa podie\u013ea na vytvoren\u00ed spolo\u010dnej hash tabu\u013eky.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-sliyaniem--merge-join\">Spojenie zlu\u010den\u00edm \u2014 Merge Join<\/h3>\n<p><\/p>\n<p>Spojenie zlu\u010den\u00edm je vo svojej podstate neparaleln\u00e9. Nebojte sa, ak je to posledn\u00e1 f\u00e1za dotazu, st\u00e1le m\u00f4\u017ee by\u0165 vykon\u00e1van\u00e1 paralelne.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">-- Dotaz 2 z TPC-H\nvysvetli\u0165 (n&aacute;klady off) vyberte s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment\nz    part, supplier, partsupp, nation, region\nkde\n        p_partkey = ps_partkey\n        a s_suppkey = ps_suppkey\n        a p_size = 36\n        a p_type ako &#039;%BRASS&#039;\n        a s_nationkey = n_nationkey\n        a n_regionkey = r_regionkey\n        a r_name = &#039;AMERICA&#039;\n        a ps_supplycost = (\n                vyberte\n                        min(ps_supplycost)\n                z    partsupp, supplier, nation, region\n                kde\n                        p_partkey = ps_partkey\n                        a s_suppkey = ps_suppkey\n                        a s_nationkey = n_nationkey\n                        a n_regionkey = r_regionkey\n                        a r_name = &#039;AMERICA&#039;\n        )\nporadie pod\u013ea s_acctbal zostupne, n_name, s_name, p_partkey\nLIMIT 100;\n                                                PL&Aacute;N DOTAZU\n----------------------------------------------------------------------------------------------------------\n Limit\n   -&amp;gt;  Triedi\u0165\n         K\u013e&uacute;\u010d triedenia: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey\n         -&amp;gt;  Merge Join\n               Merge Cond: (part.p_partkey = partsupp.ps_partkey)\n               Join Filter: (partsupp.ps_supplycost = (SubPlan 1))\n               -&amp;gt;  Gather Merge\n                     Pl&aacute;novan&iacute; pracuj&uacute;ci: 4\n                     -&amp;gt;  Paraleln&yacute; indexov&yacute; sken pomocou &lt;strong&gt;part_pkey&lt;\/strong&gt; na \u010dasti\n                           Filter: (((p_type)::text ~~ &#039;%BRASS&#039;::text) A (p_size = 36))\n               -&amp;gt;  Materializova\u0165\n                     -&amp;gt;  Triedi\u0165\n                           K\u013e&uacute;\u010d triedenia: partsupp.ps_partkey\n                           -&amp;gt;  Vnoren&aacute; slu\u010dka\n                                 -&amp;gt;  Vnoren&aacute; slu\u010dka\n                                       Join Filter: (nation.n_regionkey = region.r_regionkey)\n                                       -&amp;gt;  Sekven\u010dn&yacute; sken na region\n                                             Filter: (r_name = &#039;AMERICA&#039;::bpchar)\n                                       -&amp;gt;  Hash Join\n                                             Hash Cond: (supplier.s_nationkey = nation.n_nationkey)\n                                             -&amp;gt;  Sekven\u010dn&yacute; sken na supplier\n                                             -&amp;gt;  Hash\n                                                   -&amp;gt;  Sekven\u010dn&yacute; sken na nation\n                                 -&amp;gt;  Index Scan pomocou idx_partsupp_suppkey na partsupp\n                                       Index Cond: (ps_suppkey = supplier.s_suppkey)\n               SubPlan 1\n                 -&amp;gt;  Agregova\u0165\n                       -&amp;gt;  Vnoren&aacute; slu\u010dka\n                             Join Filter: (nation_1.n_regionkey = region_1.r_regionkey)\n                             -&amp;gt;  Sekven\u010dn&yacute; sken na region region_1\n                                   Filter: (r_name = &#039;AMERICA&#039;::bpchar)\n                             -&amp;gt;  Vnoren&aacute; slu\u010dka\n                                   -&amp;gt;  Vnoren&aacute; slu\u010dka\n                                         -&amp;gt;  Index Scan pomocou idx_partsupp_partkey na partsupp partsupp_1\n                                               Index Cond: (part.p_partkey = ps_partkey)\n                                         -&amp;gt;  Index Scan pomocou supplier_pkey na supplier supplier_1\n                                               Index Cond: (s_suppkey = partsupp_1.ps_suppkey)\n                                   -&amp;gt;  Index Scan pomocou nation_pkey na nation nation_1\n                                         Index Cond: (n_nationkey = supplier_1.s_nationkey)<\/code><\/pre>\n<p><\/p>\n<p>N\u00f3da \u00abMerge Join\u00bb je nad \u00abGather Merge\u00bb. Tak\u017ee zl\u00fa\u010denie nevyu\u017e\u00edva paraleln\u00e9 spracovanie. Ale n\u00f3da \u00abParallel Index Scan\u00bb st\u00e1le pom\u00e1ha so segmentom <code>part_pkey<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-po-sekciyam\">Spojenie pod\u013ea sekci\u00ed<\/h3>\n<p><\/p>\n<p>V PostgreSQL 11 <noindex><a rel=\"nofollow\" href=\"http:\/\/ashutoshpg.blogspot.com\/2017\/12\/partition-wise-joins-divide-and-conquer.html\">spojenie pod\u013ea sekci\u00ed<\/a><\/noindex> je predvolene vypnut\u00e9: m\u00e1 ve\u013emi n\u00e1kladn\u00e9 pl\u00e1novanie. Tabu\u013eky so podobn\u00fdm sekcionovan\u00edm je mo\u017en\u00e9 sp\u00e1ja\u0165 sekciu za sekciou. Tak Postgres pou\u017eije men\u0161ie hash tabu\u013eky. Ka\u017ed\u00e9 spojenie sekci\u00ed m\u00f4\u017ee by\u0165 paraleln\u00e9.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">tpch=# set enable_partitionwise_join=t;\ntpch=# explain (costs off) select * from prt1 t1, prt2 t2\nwhere t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;\n                    PL\u00c1N DOTAZU\n---------------------------------------------------\n Append\n   -&gt;  Hash Join\n         Hash Cond: (t2.b = t1.a)\n         -&gt;  Seq Scan on prt2_p1 t2\n               Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n         -&gt;  Hash\n               -&gt;  Seq Scan on prt1_p1 t1\n                     Filter: (b = 0)\n   -&gt;  Hash Join\n         Hash Cond: (t2_1.b = t1_1.a)\n         -&gt;  Seq Scan on prt2_p2 t2_1\n               Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n         -&gt;  Hash\n               -&gt;  Seq Scan on prt1_p2 t1_1\n                     Filter: (b = 0)\ntpch=# set parallel_setup_cost = 1;\ntpch=# set parallel_tuple_cost = 0.01;\ntpch=# explain (costs off) select * from prt1 t1, prt2 t2\nwhere t1.a = t2.b and t1.b = 0 and t2.b between 0 and 10000;\n                        PL\u00c1N DOTAZU\n-----------------------------------------------------------\n Gather\n   Workers Planned: 4\n   -&gt;  Paraleln\u00fd Append\n         -&gt;  Paraleln\u00fd Hash Join\n               Hash Cond: (t2_1.b = t1_1.a)\n               -&gt;  Paraleln\u00fd Seq Scan on prt2_p2 t2_1\n                     Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n               -&gt;  Paraleln\u00fd Hash\n                     -&gt;  Paraleln\u00fd Seq Scan on prt1_p2 t1_1\n                           Filter: (b = 0)\n         -&gt;  Paraleln\u00fd Hash Join\n               Hash Cond: (t2.b = t1.a)\n               -&gt;  Paraleln\u00fd Seq Scan on prt2_p1 t2\n                     Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n               -&gt;  Paraleln\u00fd Hash\n                     -&gt;  Paraleln\u00fd Seq Scan on prt1_p1 t1\n                           Filter: (b = 0)<\/code><\/pre>\n<p><\/p>\n<p>Hlavn\u00e9 je, \u017ee spojenie pod\u013ea sekci\u00ed m\u00f4\u017ee by\u0165 paraleln\u00e9, len ak s\u00fa tieto sekcie dostato\u010dne ve\u013ek\u00e9.<\/p>\n<p><\/p>\n<h3 id=\"parallelnoe-dopolnenie--parallel-append\">Paraleln\u00e9 doplnenie \u2014 Parallel Append<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/parallel-plans.html#PARALLEL-APPEND\">Parallel Append<\/a><\/noindex> m\u00f4\u017ee by\u0165 pou\u017eit\u00e9 namiesto r\u00f4znych blokov v r\u00f4znych pracovn\u00fdch procesoch. Zvy\u010dajne ide o dotazy UNION ALL. Nev\u00fdhodou je men\u0161\u00ed paralelizmus, preto\u017ee ka\u017ed\u00fd pracovn\u00fd proces spracov\u00e1va len 1 dotaz.<\/p>\n<p><\/p>\n<p>Tu s\u00fa spusten\u00e9 2 pracovn\u00e9 procesy, hoci s\u00fa zapnut\u00e9 4.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">tpch=# explain (costs off) select sum(l_quantity) as sum_qty from lineitem where l_shipdate &lt;= date &#039;1998-12-01&#039; - interval &#039;105&#039; day union all select sum(l_quantity) as sum_qty from lineitem where l_shipdate   Parallel Append\n         -&gt;  Aggregate\n               -&gt;  Seq Scan on lineitem\n                     Filter: (l_shipdate   Aggregate\n               -&gt;  Seq Scan on lineitem lineitem_1\n                     Filter: (l_shipdate &lt;= &#039;1998-08-18 00:00:00&#039;::timestamp without time zone)<\/code><\/pre>\n<p><\/p>\n<h3 id=\"samye-vazhnye-peremennye\">Najd\u00f4le\u017eitej\u0161ie premenn\u00e9<\/h3>\n<p><\/p>\n<ul>\n<li>WORK_MEM obmedzuje objem pam\u00e4te pre ka\u017ed\u00fd proces, nielen pre dopyty: work_mem <em> procesy <\/em> pripojenia = ve\u013emi ve\u013ea pam\u00e4te.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-PARALLEL-WORKERS-PER-GATHER\"><code>max_parallel_workers_per_gather<\/code><\/a><\/noindex> \u2014 ko\u013eko pracovn\u00fdch procesov vykon\u00e1vaj\u00faca \u00faloha pou\u017eije na paraleln\u00e9 spracovanie z pl\u00e1nu.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES\"><code>max_worker_processes<\/code><\/a><\/noindex> \u2014 prisp\u00f4sobuje celkov\u00fd po\u010det pracovn\u00fdch procesov k po\u010dtu jadier CPU na serveri.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/runtime-config-resource.html#GUC-MAX-WORKER-PROCESSES\"><code>max_parallel_workers<\/code><\/a><\/noindex> \u2014 to ist\u00e9, ale pre paraleln\u00e9 pracovn\u00e9 procesy.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"itogi\">Zhrnutie<\/h3>\n<p><\/p>\n<p>Od verzie 9.6 m\u00f4\u017ee paraleln\u00e9 spracovanie v\u00fdrazne zlep\u0161i\u0165 v\u00fdkon zlo\u017eit\u00fdch dopytov, ktor\u00e9 skenuj\u00fa ve\u013ea riadkov alebo indexov. V PostgreSQL 10 je paraleln\u00e9 spracovanie predvolene zapnut\u00e9. Nezabudnite ho vypn\u00fa\u0165 na serveroch s ve\u013ek\u00fdm za\u0165a\u017een\u00edm OLTP. Sekven\u010dn\u00e9 skeny alebo skeny indexov spotreb\u00favaj\u00fa ve\u013emi ve\u013ea zdrojov. Ak nevykon\u00e1vate report na cel\u00fa sadu \u00fadajov, m\u00f4\u017eete dopyty spravi\u0165 efekt\u00edvnej\u0161\u00edmi jednoducho pridan\u00edm ch\u00fdbaj\u00facich indexov alebo pou\u017eit\u00edm spr\u00e1vneho \u010dlenenia.<\/p>\n<p><\/p>\n<h3 id=\"ssylki\">Odkazy<\/h3>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/how-parallel-query-works.html\">https:\/\/www.postgresql.org\/docs\/11\/how-parallel-query-works.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/parallel-plans.html\">https:\/\/www.postgresql.org\/docs\/11\/parallel-plans.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/ashutoshpg.blogspot.com\/2017\/12\/partition-wise-joins-divide-and-conquer.html\">http:\/\/ashutoshpg.blogspot.com\/2017\/12\/partition-wise-joins-divide-and-conquer.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/rhaas.blogspot.com\/2016\/04\/postgresql-96-with-parallel-query-vs.html\">http:\/\/rhaas.blogspot.com\/2016\/04\/postgresql-96-with-parallel-query-vs.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/amitkapila16.blogspot.com\/2015\/11\/parallel-sequential-scans-in-play.html\">http:\/\/amitkapila16.blogspot.com\/2015\/11\/parallel-sequential-scans-in-play.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/write-skew.blogspot.com\/2018\/01\/parallel-hash-for-postgresql.html\">https:\/\/write-skew.blogspot.com\/2018\/01\/parallel-hash-for-postgresql.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/rhaas.blogspot.com\/2017\/03\/parallel-query-v2.html\">http:\/\/rhaas.blogspot.com\/2017\/03\/parallel-query-v2.html<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/blog.2ndquadrant.com\/parallel-monster-benchmark\/\">https:\/\/blog.2ndquadrant.com\/parallel-monster-benchmark\/<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/blog.2ndquadrant.com\/parallel-aggregate\/\">https:\/\/blog.2ndquadrant.com\/parallel-aggregate\/<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.depesz.com\/2018\/02\/12\/waiting-for-postgresql-11-support-parallel-btree-index-builds\/\">https:\/\/www.depesz.com\/2018\/02\/12\/waiting-for-postgresql-11-support-parallel-btree-index-builds\/<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/jWIOZzezbb8\">Paralelizmus v PostgreSQL 11<\/a><\/noindex><\/li>\n<\/ul>\n<p>Zdroj: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/446706\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0426\u041f \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u044f\u0434\u0435\u0440. \u0413\u043e\u0434\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u044b\u043b\u0430\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043e\u0442\u0447\u0435\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u0441\u0442\u0440\u043e\u043a \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435, \u043e\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0426\u041f, \u0438 \u0432 PostgreSQL \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 9.6. \u041f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c 3 \u0433\u043e\u0434\u0430, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u2014 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u044d\u0442\u0430\u043f\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22879,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30900","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0426\u041f \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u044f\u0434\u0435\u0440.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sk_SK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 PostgreSQL | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0426\u041f \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u044f\u0434\u0435\u0440.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:38:02+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:38:02+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Paraleln\u00e9 dopyty v PostgreSQL | ProHoster","description":"V modern\u00fdch CPU je ve\u013emi ve\u013ea jadier.","canonical_url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sk_SK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 PostgreSQL | ProHoster","og:description":"\u0412 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0426\u041f \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u044f\u0434\u0435\u0440.","og:url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:38:02+00:00","article:modified_time":"2019-10-31T18:38:02+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30900","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 03:34:04","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:27:06","updated":"2026-01-21 03:34:04","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/30900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/comments?post=30900"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/30900\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media\/22879"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media?parent=30900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/categories?post=30900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/tags?post=30900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}