{"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\/sv\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","title":{"rendered":"Parallella f\u00f6rfr\u00e5gningar i PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Parallella f\u00f6rfr\u00e5gningar i PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/04\/bbb4b4d3f8714bbdb9b26ada2f2253b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nI moderna CPU:er finns det m\u00e5nga k\u00e4rnor. Under flera \u00e5r har applikationer skickat f\u00f6rfr\u00e5gningar till databaser parallellt. Om det \u00e4r en rapportf\u00f6rfr\u00e5gan om m\u00e5nga rader i en tabell utf\u00f6rs den snabbare n\u00e4r flera CPU:er \u00e4r involverade, och i PostgreSQL \u00e4r detta m\u00f6jligt sedan version 9.6.<\/p>\n<p><\/p>\n<p>Det tog tre \u00e5r att implementera funktionen f\u00f6r parallella f\u00f6rfr\u00e5gningar \u2013 koden beh\u00f6vde skrivas om vid olika steg i f\u00f6rfr\u00e5gningarnas utf\u00f6rande. PostgreSQL 9.6 introducerade infrastrukturen f\u00f6r att ytterligare f\u00f6rb\u00e4ttra koden. I senare versioner utf\u00f6rs \u00e4ven andra typer av f\u00f6rfr\u00e5gningar parallellt.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"ogranicheniya\">Begr\u00e4nsningar<\/h3>\n<p><\/p>\n<ul>\n<li>Aktivera inte parallell exekvering om alla k\u00e4rnor redan \u00e4r upptagna, annars kommer andra f\u00f6rfr\u00e5gningar att bromsa.<\/li>\n<li>Det viktigaste \u00e4r att parallell behandling med h\u00f6ga values WORK_MEM anv\u00e4nder mycket minne \u2013 varje hash-f\u00f6rbindelse eller sortering tar minne motsvarande work_mem.<\/li>\n<li>OLTP-f\u00f6rfr\u00e5gningar med l\u00e5g latens kan inte \u00f6ka hastigheten med parallell exekvering. Om en f\u00f6rfr\u00e5gan returnerar en rad kommer den parallella behandlingen bara att sakta ner den.<\/li>\n<li>Utvecklare \u00e4lskar att anv\u00e4nda TPC-H-benchmarken. Kanske har du liknande f\u00f6rfr\u00e5gningar f\u00f6r perfekt parallell exekvering.<\/li>\n<li>Endast SELECT-f\u00f6rfr\u00e5gningar utan predikantl\u00e5sning utf\u00f6rs parallellt.<\/li>\n<li>Ibland kan r\u00e4tt indexering vara b\u00e4ttre \u00e4n sekventiell skanning av tabellen i parallell l\u00e4ge.<\/li>\n<li>Stopp av f\u00f6rfr\u00e5gningar och mark\u00f6rer st\u00f6ds inte.<\/li>\n<li>F\u00f6nsterfunktioner och aggregerade funktioner av ordnade upps\u00e4ttningar \u00e4r inte parallella.<\/li>\n<li>Du vinner inget i in- och utdataarbetsbelastning.<\/li>\n<li>Det finns inga parallella sorteringsalgoritmer. Men f\u00f6rfr\u00e5gningar med sorteringar kan exekveras parallellt i vissa aspekter.<\/li>\n<li>Ers\u00e4tt CTE (WITH \u2026) med en inb\u00e4ddad SELECT f\u00f6r att inkludera parallell bearbetning.<\/li>\n<li>Wraps f\u00f6r tredjepartsdata st\u00f6der fortfarande inte parallell bearbetning (men det skulle kunna!)<\/li>\n<li>FULL OUTER JOIN st\u00f6ds inte.<\/li>\n<li>max_rows inaktiverar parallell bearbetning.<\/li>\n<li>Om en f\u00f6rfr\u00e5gan inneh\u00e5ller en funktion som inte \u00e4r markerad som PARALLEL SAFE kommer den att vara en-tr\u00e5dad.<\/li>\n<li>Transaktionsisoleringsniv\u00e5n SERIALIZABLE inaktiverar parallell bearbetning.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"testovaya-sreda\">Testmilj\u00f6<\/h3>\n<p><\/p>\n<p>PostgreSQL-utvecklarna f\u00f6rs\u00f6kte minska svarstiden f\u00f6r TPC-H-benchmarkf\u00e5gor. Ladda ner benchmarken och <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">anpassa den till PostgreSQL<\/a><\/noindex>. Detta \u00e4r ett icke-officiellt anv\u00e4ndande av TPC-H-benchmarken \u2013 inte f\u00f6r att j\u00e4mf\u00f6ra databaser eller h\u00e5rdvara.<\/p>\n<p><\/p>\n<ol>\n<li>Ladda ner TPC-H_Tools_v2.17.3.zip (eller nyare version) <noindex><a rel=\"nofollow\" href=\"http:\/\/www.tpc.org\/tpc_documents_current_versions\/current_specifications.asp\">fr\u00e5n TPC:s officiella webbplats<\/a><\/noindex>.<\/li>\n<li>\u00c4ndra namnet p\u00e5 makefile.suite till Makefile och som beskrivs h\u00e4r: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">https:\/\/github.com\/tvondra\/pg_tpch <\/a><\/noindex>. Kompilera koden med kommandot make.<\/li>\n<li>Generera data: <code>.\/dbgen -s 10<\/code> skapar en databas p\u00e5 23 GB. Det r\u00e4cker f\u00f6r att se skillnaden i prestanda mellan parallella och icke-parallella f\u00f6rfr\u00e5gningar.<\/li>\n<li>Konvertera filer <code>tbl<\/code> p\u00e5 <code>csv till f\u00f6r<\/code> och <code>sed<\/code>.<\/li>\n<li>Klona repositoriet <code>pg_tpch<\/code> och kopiera filerna <code>csv<\/code> p\u00e5 <code>pg_tpch\/dss\/data<\/code>.<\/li>\n<li>Skapa f\u00f6rfr\u00e5gningar med kommandot <code>qgen<\/code>.<\/li>\n<li>Ladda upp data i databasen med kommandot <code>.\/tpch.sh<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"parallelnoe-posledovatelnoe-skanirovanie\">Parallell sekventiell skanning<\/h3>\n<p><\/p>\n<p>Det kan vara snabbare, inte f\u00f6r att data l\u00e4ses parallellt, utan eftersom data sprids \u00f6ver m\u00e5nga CPU-k\u00e4rnor. I moderna operativsystem cachas PostgreSQL-datafiler v\u00e4l. Med f\u00f6rhandsl\u00e4sning kan man h\u00e4mta fler block fr\u00e5n lagringen \u00e4n vad PG-processen beg\u00e4r. D\u00e4rf\u00f6r begr\u00e4nsas f\u00f6rfr\u00e5gningsprestandan inte av diskens I\/O. Den anv\u00e4nder CPU-cykler f\u00f6r att:<\/p>\n<p><\/p>\n<ul>\n<li>l\u00e4sa rader en och en fr\u00e5n tabellens sidor;<\/li>\n<li>j\u00e4mf\u00f6ra v\u00e4rden och villkor f\u00f6r rader. <code>D\u00c4R<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>L\u00e5t oss utf\u00f6ra en enkel f\u00f6rfr\u00e5gning <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;= date &#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) (actual time=0.014..16951.669 rows=58839715 loops=1)\nFilter: (l_shipdate &lt;= &#039;1998-08-18 00:00:00&#039;::timestamp without time zone)\nRows Removed by Filter: 1146337\nPlanning Time: 0.203 ms\nExecution Time: 19035.100 ms<\/code><\/pre>\n<p><\/p>\n<p>Sekventiell skanning ger f\u00f6r m\u00e5nga rader utan aggregering, s\u00e5 f\u00f6rfr\u00e5gan k\u00f6rs med en enda CPU-k\u00e4rna.<\/p>\n<p><\/p>\n<p>Om man l\u00e4gger till <code>SUM()<\/code>, syns det att tv\u00e5 arbetstr\u00e5dar hj\u00e4lper till att p\u00e5skynda f\u00f6rfr\u00e5gan:<\/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) (actual time=8553.241..8555.067 rows=3 loops=1)\nWorkers Planned: 2\nWorkers Launched: 2\n-&gt; Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)\n-&gt; Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)\nFilter: (l_shipdate &lt;= &#039;1998-08-18 00:00:00&#039;::timestamp without time zone)\nRows Removed by Filter: 382112\nPlanning Time: 0.241 ms\nExecution Time: 8555.131 ms<\/code><\/pre>\n<p><\/p>\n<h3 id=\"parallelnaya-agregaciya\">Parallell aggregering<\/h3>\n<p><\/p>\n<p>Noden &#171;Parallel Seq Scan&#187; producerar rader f\u00f6r partiell aggregering. Noden &#171;Partial Aggregate&#187; besk\u00e4r dessa rader med hj\u00e4lp av <code>SUM()<\/code>. I slutet samlas SUM-r\u00e4knaren fr\u00e5n varje arbetsprocess av noden &#171;Gather&#187;.<\/p>\n<p><\/p>\n<p>Det slutgiltiga resultatet ber\u00e4knas av noden &#171;Finalize Aggregate&#187;. Om du har egna aggregeringsfunktioner, kom ih\u00e5g att m\u00e4rka dem som &#171;parallel safe&#187;.<\/p>\n<p><\/p>\n<h3 id=\"kolichestvo-rabochih-processov\">Antal arbetsprocesser<\/h3>\n<p><\/p>\n<p>Antalet arbetsprocesser kan \u00f6kas utan att starta om servern:<\/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) (actual time=8553.241..8555.067 rows=3 loops=1)\nWorkers Planned: 2\nWorkers Launched: 2\n-&gt; Partial Aggregate (cost=1588701.91..1588701.92 rows=1 width=32) (actual time=8547.546..8547.546 rows=1 loops=3)\n-&gt; Parallel Seq Scan on lineitem (cost=0.00..1527393.33 rows=24523431 width=5) (actual time=0.038..5998.417 rows=19613238 loops=3)\nFilter: (l_shipdate &lt;= &#039;1998-08-18 00:00:00&#039;::timestamp without time zone)\nRows Removed by Filter: 382112\nPlanning Time: 0.241 ms\nExecution Time: 8555.131 ms<\/code><\/pre>\n<p><\/p>\n<p>Vad h\u00e4nder h\u00e4r? Antalet arbetsprocesser har blivit dubbelt s\u00e5 m\u00e5nga, men f\u00f6rfr\u00e5gan blev bara 1,6599 g\u00e5nger snabbare. Ber\u00e4kningarna \u00e4r intressanta. Vi hade 2 arbetsprocesser och 1 ledare. Efter f\u00f6r\u00e4ndringen blev det 4+1.<\/p>\n<p><\/p>\n<p>V\u00e5r maximala hastighets\u00f6kning fr\u00e5n parallell bearbetning: 5\/3 = 1,66(6) g\u00e5nger.<\/p>\n<p><\/p>\n<h2 id=\"kak-eto-rabotaet\">Hur fungerar det?<\/h2>\n<p><\/p>\n<h3 id=\"processy\">Processer<\/h3>\n<p><\/p>\n<p>Utf\u00f6randet av en f\u00f6rfr\u00e5gan b\u00f6rjar alltid med ledarprocessen. Ledaren g\u00f6r allt icke-parallellt och en del av den parallella bearbetningen. Andra processer som utf\u00f6r samma f\u00f6rfr\u00e5gningar kallas arbetsprocesser. Parallell bearbetning anv\u00e4nder infrastrukturen <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/bgworker.html\">av dynamiska bakgrundsarbetare<\/a><\/noindex> (fr\u00e5n version 9.4). Eftersom andra delar av PostgreSQL anv\u00e4nder processer ist\u00e4llet f\u00f6r tr\u00e5dar, kunde en f\u00f6rfr\u00e5gan med 3 arbetsprocesser vara 4 g\u00e5nger snabbare \u00e4n traditionell bearbetning.<\/p>\n<p><\/p>\n<h3 id=\"vzaimodeystvie\">Interaktion<\/h3>\n<p><\/p>\n<p>Arbetsprocesserna kommunicerar med ledaren via ett meddelandek\u00f6 (baserat p\u00e5 delad minne). Varje process har 2 k\u00f6er: f\u00f6r fel och f\u00f6r tupler.<\/p>\n<p><\/p>\n<h3 id=\"skolko-nuzhno-rabochih-processov\">Hur m\u00e5nga arbetsprocesser beh\u00f6vs?<\/h3>\n<p><\/p>\n<p>Det minimi begr\u00e4nsning som st\u00e4lls in av parametern <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>. Sedan h\u00e4mtar fr\u00e5geexecutorn arbetsprocesser fr\u00e5n poolen, begr\u00e4nsad av parametern <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>. Den sista begr\u00e4nsningen \u00e4r <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>, det vill s\u00e4ga det totala antalet bakgrundsprocesser.<\/p>\n<p><\/p>\n<p>Om det inte g\u00e5r att tilldela en arbetsprocess, kommer bearbetningen att vara enprocessig.<\/p>\n<p><\/p>\n<p>Fr\u00e5geplaneraren kan minska arbetsprocesser beroende p\u00e5 storleken av tabellen eller indexet. Det finns parametrar f\u00f6r detta: <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> och <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-tabell =&gt; 1 arbetare\n24MB-tabell =&gt; 2 arbetare\n72MB-tabell =&gt; 3 arbetare\nx =&gt; log(x \/ min_parallel_table_scan_size) \/ log(3) + 1 arbetare<\/code><\/pre>\n<p><\/p>\n<p>Varje g\u00e5ng tabellen \u00e4r tre g\u00e5nger st\u00f6rre \u00e4n <code>min_parallel_(index|table)_scan_size<\/code>, l\u00e4gger Postgres till en arbetsprocess. Antalet arbetsprocesser baseras inte p\u00e5 kostnader. Cykelberoendet g\u00f6r komplexa implementationer sv\u00e5ra. Ist\u00e4llet anv\u00e4nder planeraren enkla regler.<\/p>\n<p><\/p>\n<p>I praktiken \u00e4r dessa regler inte alltid l\u00e4mpliga f\u00f6r produktion, s\u00e5 man kan \u00e4ndra antalet arbetsprocesser f\u00f6r en specifik tabell: ALTER TABLE \u2026 SET (<code>parallel_workers = N<\/code>).<\/p>\n<p><\/p>\n<h3 id=\"pochemu-parallelnaya-obrabotka-ne-ispolzuetsya\">Varf\u00f6r anv\u00e4nds inte parallell bearbetning?<\/h3>\n<p><\/p>\n<p>F\u00f6rutom den l\u00e5nga listan \u00f6ver begr\u00e4nsningar finns det \u00e4ven kostnadskontroller:<\/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 f\u00f6r att undvika parallell bearbetning av korta f\u00f6rfr\u00e5gningar. Denna parameter uppskattar tiden f\u00f6r att f\u00f6rbereda minnet, starta processen och initialt utbyta data.<\/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>: ledarens kommunikation med arbetarna kan f\u00f6rl\u00e4ngas proportionellt mot antalet tuples fr\u00e5n arbetande processer. Denna parameter ber\u00e4knar kostnaderna f\u00f6r datautbyte.<\/p>\n<p><\/p>\n<h3 id=\"soedineniya-vlozhennyh-ciklov--nested-loop-join\">N\u00e4stlad loopsammanfogning \u2014 Nested Loop Join<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">PostgreSQL 9.6+ kan utf\u00f6ra inb\u00e4ddade loopar parallellt \u2014 detta \u00e4r en enkel operation.\n\nexplain (costs off) select c_custkey, count(o_orderkey)\n from customer left outer join orders on\n c_custkey = o_custkey and o_comment not like '%specialposits%'\n group by c_custkey;\n QUERY PLAN\n--------------------------------------------------------------------------------------\n Finalize GroupAggregate\n Group Key: customer.c_custkey\n -&gt; Gather Merge\n Workers Planned: 4\n -&gt; Partial GroupAggregate\n Group Key: customer.c_custkey\n -&gt; Nested Loop Left Join\n -&gt; Parallel Index Only Scan using customer_pkey on customer\n -&gt; Index Scan using idx_orders_custkey on orders\n Index Cond: (customer.c_custkey = o_custkey)\n Filter: ((o_comment)::text !~~ '%specialposits%'::text)<\/code><\/pre>\n<p><\/p>\n<p>Samlingsprocessen sker i det sista steget, s\u00e5 Nested Loop Left Join \u00e4r en parallell operation. Parallel Index Only Scan introducerades f\u00f6rst i version 10. Det fungerar p\u00e5 samma s\u00e4tt som ett parallellt sekventiellt scan. Villkoret <code>c_custkey = o_custkey<\/code> l\u00e4ser en order f\u00f6r varje kundrad. S\u00e5 det \u00e4r inte parallellt.<\/p>\n<p><\/p>\n<h3 id=\"hesh-soedinenie--hash-join\">Hash-sammanfogning \u2014 Hash Join<\/h3>\n<p><\/p>\n<p>Varje arbetsprocess skapar sin egen hash-tabell fram till PostgreSQL 11. Och om det finns fler \u00e4n fyra s\u00e5dana processer \u00f6kar inte prestandan. I den nya versionen \u00e4r hash-tabellen gemensam. Varje arbetsprocess kan anv\u00e4nda WORK_MEM f\u00f6r att skapa en hash-tabell.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">v\u00e4lj\n        l_shipmode,\n        summa(fall\n                n\u00e4r o_orderpriority = '1-URGENT'\n                        eller o_orderpriority = '2-HIGH'\n                        d\u00e5 1\n                annars 0\n        slut) som high_line_count,\n        summa(fall\n                n\u00e4r o_orderpriority &lt;&gt; '1-URGENT'\n                        och o_orderpriority &lt;&gt; '2-HIGH'\n                        d\u00e5 1\n                annars 0\n        slut) som low_line_count\nfr\u00e5n\n        orders,\n        lineitem\nvar\n        o_orderkey = l_orderkey\n        och l_shipmode i ('MAIL', 'AIR')\n        och l_commitdate &lt; l_receiptdate\n        och l_shipdate &lt; l_commitdate\n        och l_receiptdate &gt;= datum '1996-01-01'\n        och l_receiptdate &lt; datum '1996-01-01' + intervall '1' \u00e5r\ngrupp efter\n        l_shipmode\nordna efter\n        l_shipmode\nBEGR\u00c4NSA 1;\n                                                                                                                                    QUERY PLAN\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n Begr\u00e4nsning  (kostnad=1964755.66..1964961.44 rader=1 bred=27) (aktuell tid=7579.592..7922.997 rader=1 loop=1)\n   -&gt;  Avsluta GroupAggregate  (kostnad=1964755.66..1966196.11 rader=7 bred=27) (aktuell tid=7579.590..7579.591 rader=1 loop=1)\n         Gruppnyckel: lineitem.l_shipmode\n         -&gt;  Samla Samman  (kostnad=1964755.66..1966195.83 rader=28 bred=27) (aktuell tid=7559.593..7922.319 rader=6 loop=1)\n               Arbetare Planerade: 4\n               Arbetare Startade: 4\n               -&gt;  Delad GroupAggregate  (kostnad=1963755.61..1965192.44 rader=7 bred=27) (aktuell tid=7548.103..7564.592 rader=2 loop=5)\n                     Gruppnyckel: lineitem.l_shipmode\n                     -&gt;  Sortera  (kostnad=1963755.61..1963935.20 rader=71838 bred=27) (aktuell tid=7530.280..7539.688 rader=62519 loop=5)\n                           Sorteringsnyckel: lineitem.l_shipmode\n                           Sorteringsmetod: extern sammanfogning  Disk: 2304kB\n                           Arbetare 0:  Sorteringsmetod: extern sammanfogning  Disk: 2064kB\n                           Arbetare 1:  Sorteringsmetod: extern sammanfogning  Disk: 2384kB\n                           Arbetare 2:  Sorteringsmetod: extern sammanfogning  Disk: 2264kB\n                           Arbetare 3:  Sorteringsmetod: extern sammanfogning  Disk: 2336kB\n                           -&gt;  Parallell Hash Join  (kostnad=382571.01..1957960.99 rader=71838 bred=27) (aktuell tid=7036.917..7499.692 rader=62519 loop=5)\n                                 Hash Villkor: (lineitem.l_orderkey = orders.o_orderkey)\n                                 -&gt;  Parallell Sekventiell Skanning p\u00e5 lineitem  (kostnad=0.00..1552386.40 rader=71838 bred=19) (aktuell tid=0.583..4901.063 rader=62519 loop=5)\n                                       Filter: ((l_shipmode = VALFRI ('{MAIL,AIR}'::bpchar[])) OCH (l_commitdate &lt; l_receiptdate) OCH (l_shipdate &lt; l_commitdate) OCH (l_receiptdate &gt;= '1996-01-01'::datum) OCH (l_receiptdate &lt; '1997-01-01 00:00:00'::tidsst\u00e4mpel utan tidszon))\n                                       Rader Borttagna av Filter: 11934691\n                                 -&gt;  Parallell Hash  (kostnad=313722.45..313722.45 rader=3750045 bred=20) (aktuell tid=2011.518..2011.518 rader=3000000 loop=5)\n                                       Bucket: 65536  Batch: 256  Minnesbruk: 3840kB\n                                       -&gt;  Parallell Sekventiell Skanning p\u00e5 orders  (kostnad=0.00..313722.45 rader=3750045 bred=20) (aktuell tid=0.029..995.948 rader=3000000 loop=5)\n Planeringstid: 0.977 ms\n Utf\u00f6randeavdelningstid: 7923.770 ms<\/code><\/pre>\n<p><\/p>\n<p>Fr\u00e5ga 12 fr\u00e5n TPC-H visar tydligt en parallell hash-f\u00f6rbindelse. Varje arbetare deltar i att skapa en gemensam hash-tabell.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-sliyaniem--merge-join\">Sammanl\u00e4ggning \u2014 Merge Join<\/h3>\n<p><\/p>\n<p>Sammanl\u00e4ggning som inte \u00e4r parallell till sin natur. Oroa dig inte om detta \u00e4r det sista steget i f\u00f6rfr\u00e5gan, den kan fortfarande utf\u00f6ras parallellt.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">-- F&ouml;rfr&aring;gan 2 fr&aring;n TPC-H\nf&ouml;rklara (kostnader av) v&auml;lj s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment\nfr&aring;n part, supplier, partsupp, nation, region\nvar\n\t\tp_partkey = ps_partkey\n\t\toch s_suppkey = ps_suppkey\n\t\toch p_size = 36\n\t\toch p_type som &#039;%BRASS&#039;\n\t\toch s_nationkey = n_nationkey\n\t\toch n_regionkey = r_regionkey\n\t\toch r_name = &#039;AMERIKA&#039;\n\t\toch ps_supplycost = (\n\t\t\tv&auml;lj\n\t\t\tmin(ps_supplycost)\n\t\tfr&aring;n partsupp, supplier, nation, region\n\t\t\tvar\n\t\t\t\tp_partkey = ps_partkey\n\t\t\t\toch s_suppkey = ps_suppkey\n\t\t\t\toch s_nationkey = n_nationkey\n\t\t\t\toch n_regionkey = r_regionkey\n\t\t\t\toch r_name = &#039;AMERIKA&#039;\n\t\t)\nordna efter s_acctbal desc, n_name, s_name, p_partkey\nBEGR&Auml;NSA 100;\n                                                FR&Aring;GEPLAN\n----------------------------------------------------------------------------------------------------------\n Begr&auml;nsa\n   -&amp;gt;  Sortera\n         Sorteringsnyckel: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey\n         -&amp;gt;  Sammanfoga\n               Sammanfoga villkor: (part.p_partkey = partsupp.ps_partkey)\n               Join Filter: (partsupp.ps_supplycost = (SubPlan 1))\n               -&amp;gt;  Samla samman\n                     Planerade arbetare: 4\n                     -&amp;gt;  Parallell indexskanning med hj&auml;lp av &lt;strong&gt;part_pkey&lt;\/strong&gt; p&aring; del\n                           Filter: (((p_type)::text ~~ &#039;%BRASS&#039;::text) OCH (p_size = 36))\n               -&amp;gt;  Materialisera\n                     -&amp;gt;  Sortera\n                           Sorteringsnyckel: partsupp.ps_partkey\n                           -&amp;gt;  N&auml;stlad slinga\n                                 -&amp;gt;  N&auml;stlad slinga\n                                       Join Filter: (nation.n_regionkey = region.r_regionkey)\n                                       -&amp;gt;  Sekventiell skanning p&aring; region\n                                             Filter: (r_name = &#039;AMERIKA&#039;::bpchar)\n                                       -&amp;gt;  Hash-sammanfogning\n                                             Hash-villkor: (supplier.s_nationkey = nation.n_nationkey)\n                                             -&amp;gt;  Sekventiell skanning p&aring; leverant&ouml;r\n                                             -&amp;gt;  Hash\n                                                   -&amp;gt;  Sekventiell skanning p&aring; nation\n                                 -&amp;gt;  Indexskanning med hj&auml;lp av idx_partsupp_suppkey p&aring; partsupp\n                                       Indexvillkor: (ps_suppkey = supplier.s_suppkey)\n               SubPlan 1\n                 -&amp;gt;  Aggregat\n                       -&amp;gt;  N&auml;stlad slinga\n                             Join Filter: (nation_1.n_regionkey = region_1.r_regionkey)\n                             -&amp;gt;  Sekventiell skanning p&aring; region region_1\n                                   Filter: (r_name = &#039;AMERIKA&#039;::bpchar)\n                             -&amp;gt;  N&auml;stlad slinga\n                                   -&amp;gt;  N&auml;stlad slinga\n                                         -&amp;gt;  Indexskanning med hj&auml;lp av idx_partsupp_partkey p&aring; partsupp partsupp_1\n                                               Indexvillkor: (part.p_partkey = ps_partkey)\n                                         -&amp;gt;  Indexskanning med hj&auml;lp av supplier_pkey p&aring; supplier supplier_1\n                                               Indexvillkor: (s_suppkey = partsupp_1.ps_suppkey)\n                                   -&amp;gt;  Indexskanning med hj&auml;lp av nation_pkey p&aring; nation nation_1\n                                         Indexvillkor: (n_nationkey = supplier_1.s_nationkey)<\/code><\/pre>\n<p><\/p>\n<p>Noden &#171;Merge Join&#187; ligger ovanf\u00f6r &#171;Gather Merge&#187;. S\u00e5ledes anv\u00e4nder fusionen inte parallellbearbetning. Men noden &#171;Parallel Index Scan&#187; hj\u00e4lper fortfarande med segmentet. <code>part_pkey<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-po-sekciyam\">Sammanl\u00e4ggning efter sektioner<\/h3>\n<p><\/p>\n<p>I PostgreSQL 11 <noindex><a rel=\"nofollow\" href=\"http:\/\/ashutoshpg.blogspot.com\/2017\/12\/partition-wise-joins-divide-and-conquer.html\">sammanl\u00e4ggning efter sektioner<\/a><\/noindex> \u00e4r st\u00e4ngd som standard: den har mycket kostsam planering. Tabeller med liknande sektionering kan sammanl\u00e4ggas sektion f\u00f6r sektion. S\u00e5 kommer Postgres att anv\u00e4nda mindre hash-tabeller. Varje sektion kan vara parallell.<\/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                    QUERY PLAN\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                        QUERY PLAN\n-----------------------------------------------------------\n Gather\n   Workers Planned: 4\n   -&gt;  Parallel Append\n         -&gt;  Parallel Hash Join\n               Hash Cond: (t2_1.b = t1_1.a)\n               -&gt;  Parallel Seq Scan on prt2_p2 t2_1\n                     Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n               -&gt;  Parallel Hash\n                     -&gt;  Parallel Seq Scan on prt1_p2 t1_1\n                           Filter: (b = 0)\n         -&gt;  Parallel Hash Join\n               Hash Cond: (t2.b = t1.a)\n               -&gt;  Parallel Seq Scan on prt2_p1 t2\n                     Filter: ((b &gt;= 0) AND (b &lt;= 10000))\n               -&gt;  Parallel Hash\n                     -&gt;  Parallel Seq Scan on prt1_p1 t1\n                           Filter: (b = 0)<\/code><\/pre>\n<p><\/p>\n<p>Huvudsaken \u00e4r att sammanl\u00e4ggning efter sektioner endast kan vara parallell om dessa sektioner \u00e4r tillr\u00e4ckligt stora.<\/p>\n<p><\/p>\n<h3 id=\"parallelnoe-dopolnenie--parallel-append\">Parallell bilaga \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> kan anv\u00e4ndas ist\u00e4llet f\u00f6r olika block i olika arbetsprocesser. Detta intr\u00e4ffar vanligtvis med UNION ALL-f\u00f6rfr\u00e5gningar. Nackdelen \u00e4r mindre parallellism, eftersom varje arbetsprocess bara behandlar 1 f\u00f6rfr\u00e5gan.<\/p>\n<p><\/p>\n<p>H\u00e4r k\u00f6rs 2 arbetsprocesser, \u00e4ven om 4 \u00e4r aktiverade.<\/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\">De viktigaste variablerna<\/h3>\n<p><\/p>\n<ul>\n<li>WORK_MEM begr\u00e4nsar m\u00e4ngden minne f\u00f6r varje process, inte bara f\u00f6r fr\u00e5gor: work_mem <em> processer <\/em> anslutningar = v\u00e4ldigt mycket minne.<\/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 hur m\u00e5nga arbetsprocesser programmet kommer att anv\u00e4nda f\u00f6r parallell bearbetning fr\u00e5n planen.<\/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 justerar det totala antalet arbetsprocesser baserat p\u00e5 antalet CPU-k\u00e4rnor p\u00e5 servern.<\/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> \u2014samma, men f\u00f6r parallella arbetsprocesser.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"itogi\">Sammanfattning<\/h3>\n<p><\/p>\n<p>Fr\u00e5n och med version 9.6 kan parallell bearbetning avsev\u00e4rt f\u00f6rb\u00e4ttra prestandan f\u00f6r komplexa fr\u00e5gor som skannar m\u00e5nga rader eller index. I PostgreSQL 10 \u00e4r parallell bearbetning aktiverad som standard. Gl\u00f6m inte att st\u00e4nga av den p\u00e5 servrar med h\u00f6g OLTP-belastning. Sekventiella skanningar eller indexskanningar f\u00f6rbrukar mycket resurser. Om du inte k\u00f6r en rapport p\u00e5 hela datam\u00e4ngden kan fr\u00e5gor g\u00f6ras mer effektiva genom att bara l\u00e4gga till saknade index eller anv\u00e4nda korrekt partitionering.<\/p>\n<p><\/p>\n<h3 id=\"ssylki\">L\u00e4nkar<\/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\">Parallellism i PostgreSQL 11<\/a><\/noindex><\/li>\n<\/ul>\n<p>K\u00e4lla: <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\/sv\/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=\"sv_SE\" \/>\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\/sv\/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\udd47Parallella fr\u00e5gor i PostgreSQL | ProHoster","description":"Moderna CPU:er har m\u00e5nga k\u00e4rnor.","canonical_url":"https:\/\/prohoster.info\/sv\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sv_SE","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\/sv\/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\/sv\/wp-json\/wp\/v2\/posts\/30900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/comments?post=30900"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/posts\/30900\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media\/22879"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/media?parent=30900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/categories?post=30900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sv\/wp-json\/wp\/v2\/tags?post=30900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}