{"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\/it\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","title":{"rendered":"Query parallele in PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Query parallele in PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/04\/bbb4b4d3f8714bbdb9b26ada2f2253b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNei moderni CPU ci sono molti core. Da anni le applicazioni inviano richieste ai database in modo parallelo. Se si tratta di una richiesta di report su molte righe in una tabella, viene eseguita pi\u00f9 rapidamente quando utilizza pi\u00f9 CPU, e in PostgreSQL questo \u00e8 possibile a partire dalla versione 9.6.<\/p>\n<p><\/p>\n<p>Ci sono voluti 3 anni per implementare la funzione delle richieste parallele \u2014 \u00e8 stato necessario riscrivere il codice in diverse fasi dell'esecuzione delle richieste. Con PostgreSQL 9.6 \u00e8 stata introdotta un'infrastruttura per migliorare ulteriormente il codice. Nelle versioni successive anche altri tipi di richieste possono essere eseguiti in modo parallelo.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"ogranicheniya\">Limitazioni<\/h3>\n<p><\/p>\n<ul>\n<li>Non attivare l'esecuzione parallela se tutti i core sono gi\u00e0 occupati, altrimenti altre richieste subiranno ritardi.<\/li>\n<li>La cosa pi\u00f9 importante \u00e8 che l'elaborazione parallela con valori elevati di WORK_MEM utilizza molta memoria \u2014 ogni operazione di join hash o ordinamento richiede memoria in un volume pari a work_mem.<\/li>\n<li>Le richieste OLTP con bassa latenza non possono essere accelerate tramite esecuzione parallela. E se una richiesta restituisce una sola riga, l'elaborazione parallela la rallenter\u00e0.<\/li>\n<li>Gli sviluppatori amano utilizzare il benchmark TPC-H. Magari hai delle query simili per un'esecuzione parallela ideale.<\/li>\n<li>Solo le query SELECT senza blocco predicativo vengono eseguite in parallelo.<\/li>\n<li>A volte un'indicizzazione corretta \u00e8 migliore della scansione sequenziale della tabella in modalit\u00e0 parallela.<\/li>\n<li>Le sospensioni delle query e i cursori non sono supportati.<\/li>\n<li>Le funzioni di finestra e le funzioni aggregate degli insiemi ordinati non sono parallele.<\/li>\n<li>Non guadagni nulla nella carico di lavoro di input-output.<\/li>\n<li>Non esistono algoritmi di ordinamento paralleli. Ma le query con ordinamenti possono essere eseguite in parallelo in alcuni aspetti.<\/li>\n<li>Sostituisci CTE (WITH \u2026) con un SELECT annidato per includere l'elaborazione parallela.<\/li>\n<li>Le wrapper dei dati di terze parti non supportano ancora l'elaborazione parallela (ma potrebbero farlo!)<\/li>\n<li>FULL OUTER JOIN non \u00e8 supportato.<\/li>\n<li>max_rows disattiva l'elaborazione parallela.<\/li>\n<li>Se la query contiene una funzione non contrassegnata come PARALLEL SAFE, sar\u00e0 monothread.<\/li>\n<li>Il livello di isolamento della transazione SERIALIZABLE disattiva l'elaborazione parallela.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"testovaya-sreda\">Ambiente di test<\/h3>\n<p><\/p>\n<p>Gli sviluppatori di PostgreSQL hanno cercato di ridurre il tempo di risposta delle query del benchmark TPC-H. Scarica il benchmark e <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">adattalo a PostgreSQL<\/a><\/noindex>. Questo \u00e8 un uso non ufficiale del benchmark TPC-H \u2014 non per confrontare database o hardware.<\/p>\n<p><\/p>\n<ol>\n<li>Scarica TPC-H_Tools_v2.17.3.zip (o una versione pi\u00f9 recente) <noindex><a rel=\"nofollow\" href=\"http:\/\/www.tpc.org\/tpc_documents_current_versions\/current_specifications.asp\">dal sito ufficiale TPC<\/a><\/noindex>.<\/li>\n<li>Rinomina makefile.suite in Makefile e modifica come descritto qui: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">https:\/\/github.com\/tvondra\/pg_tpch <\/a><\/noindex>. Compila il codice con il comando make.<\/li>\n<li>Genera i dati: <code>.\/dbgen -s 10<\/code> crea un database di 23 GB. Questo \u00e8 sufficiente per vedere la differenza nelle prestazioni tra query parallele e non parallele.<\/li>\n<li>Converti i file <code>tbl<\/code> in <code>csv in for<\/code> e <code>sed<\/code>.<\/li>\n<li>Clona il repository <code>pg_tpch<\/code> e copia i file <code>csv<\/code> in <code>pg_tpch\/dss\/data<\/code>.<\/li>\n<li>Crea le query con il comando <code>qgen<\/code>.<\/li>\n<li>Carica i dati nel database con il comando <code>.\/tpch.sh<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"parallelnoe-posledovatelnoe-skanirovanie\">Scansione sequenziale parallela<\/h3>\n<p><\/p>\n<p>Pu\u00f2 essere pi\u00f9 veloce non a causa della lettura parallela, ma perch\u00e9 i dati sono distribuiti su molti core CPU. Nei moderni sistemi operativi, i file di dati di PostgreSQL vengono ben messi in cache. Con la lettura anticipata, \u00e8 possibile recuperare dallo storage un blocco pi\u00f9 grande di quello richiesto dal demone PG. Pertanto, le prestazioni della query non sono limitate dall'I\/O del disco. Consuma cicli CPU per:<\/p>\n<p><\/p>\n<ul>\n<li>leggere le righe una alla volta dalle pagine della tabella;<\/li>\n<li>confrontare i valori delle righe e le condizioni <code>DOVE<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>Eseguiamo una semplice query <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>La scansione sequenziale restituisce troppe righe senza aggregazione, quindi la query viene eseguita da un solo core della CPU.<\/p>\n<p><\/p>\n<p>Se aggiungi <code>SUM()<\/code>, si nota che due processi di lavoro possono aiutare ad accelerare la query:<\/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\">Aggregazione parallela<\/h3>\n<p><\/p>\n<p>Il nodo \u00abParallel Seq Scan\u00bb produce righe per l'aggregazione parziale. Il nodo \u00abPartial Aggregate\u00bb riduce queste righe utilizzando <code>SUM()<\/code>. Alla fine, il conteggio SUM di ciascun processo di lavoro viene raccolto dal nodo \u00abGather\u00bb.<\/p>\n<p><\/p>\n<p>Il risultato finale viene calcolato dal nodo \u00abFinalize Aggregate\u00bb. Se hai le tue funzioni di aggregazione, non dimenticare di contrassegnarle come \u00abparallel safe\u00bb.<\/p>\n<p><\/p>\n<h3 id=\"kolichestvo-rabochih-processov\">Numero di processi di lavoro<\/h3>\n<p><\/p>\n<p>Il numero di processi di lavoro pu\u00f2 essere aumentato senza riavviare il server:<\/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>Cosa sta succedendo qui? Il numero di processi di lavoro \u00e8 raddoppiato, mentre la query \u00e8 diventata solo 1,6599 volte pi\u00f9 veloce. I calcoli sono interessanti. Inizialmente avevamo 2 processi di lavoro e 1 leader. Dopo la modifica, abbiamo 4+1.<\/p>\n<p><\/p>\n<p>Il nostro massimo di accelerazione dalla lavorazione parallela: 5\/3 = 1,66(6) volte.<\/p>\n<p><\/p>\n<h2 id=\"kak-eto-rabotaet\">Come funziona?<\/h2>\n<p><\/p>\n<h3 id=\"processy\">Processi<\/h3>\n<p><\/p>\n<p>L'esecuzione della query inizia sempre con il processo leader. Il leader gestisce tutto il lavoro non parallelo e parte del lavoro parallelo. Gli altri processi che eseguono le stesse query sono chiamati processi di lavoro. L'elaborazione parallela utilizza l'infrastruttura <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/bgworker.html\">di processi di lavoro in background dinamici<\/a><\/noindex> (dalla versione 9.4). Poich\u00e9 le altre parti di PostgreSQL utilizzano processi invece di thread, una query con 3 processi di lavoro potrebbe essere 4 volte pi\u00f9 veloce dell'elaborazione tradizionale.<\/p>\n<p><\/p>\n<h3 id=\"vzaimodeystvie\">Interazione<\/h3>\n<p><\/p>\n<p>I processi di lavoro comunicano con il leader tramite una coda di messaggi (basata su memoria condivisa). Ogni processo ha 2 code: per gli errori e per le tuple.<\/p>\n<p><\/p>\n<h3 id=\"skolko-nuzhno-rabochih-processov\">Quanti processi di lavoro sono necessari?<\/h3>\n<p><\/p>\n<p>Il limite minimo \u00e8 stabilito dal parametro <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>. Poi l'esecutore delle query prende i processi di lavoro da un pool limitato dal parametro <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>. Il limite finale \u00e8 dato da <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>, cio\u00e8 il numero totale di processi in background.<\/p>\n<p><\/p>\n<p>Se non \u00e8 possibile allocare un processo di lavoro, l'elaborazione sar\u00e0 monoprocessore.<\/p>\n<p><\/p>\n<p>Il pianificatore delle query pu\u00f2 ridurre i processi di lavoro in base alla dimensione della tabella o dell'indice. A questo scopo vi sono i parametri <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> e <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\">imposta min_parallel_table_scan_size='8MB'\n8MB tabella =&gt; 1 processo di lavoro\n24MB tabella =&gt; 2 processi di lavoro\n72MB tabella =&gt; 3 processi di lavoro\nx =&gt; log(x \/ min_parallel_table_scan_size) \/ log(3) + 1 processo di lavoro<\/code><\/pre>\n<p><\/p>\n<p>Ogni volta che la tabella \u00e8 3 volte pi\u00f9 grande di <code>min_parallel_(index|table)_scan_size<\/code>, Postgres aggiunge un processo di lavoro. Il numero di processi di lavoro non si basa sui costi. La dipendenza circolare rende complesse le implementazioni. Invece, il pianificatore utilizza regole semplici.<\/p>\n<p><\/p>\n<p>In pratica, queste regole non sono sempre adatte per la produzione, quindi \u00e8 possibile modificare il numero di processi di lavoro per una specifica tabella: ALTER TABLE \u2026 SET (<code>parallel_workers = N<\/code>).<\/p>\n<p><\/p>\n<h3 id=\"pochemu-parallelnaya-obrabotka-ne-ispolzuetsya\">Perch\u00e9 non viene utilizzato il parallelo?<\/h3>\n<p><\/p>\n<p>Oltre a un lungo elenco di vincoli, ci sono anche controlli sui costi:<\/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 per evitare il parallelismo per le query brevi. Questo parametro stima il tempo necessario per preparare la memoria, avviare il processo e avviare lo scambio iniziale di dati.<\/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>: la comunicazione tra il leader e i lavoratori pu\u00f2 allungarsi proporzionalmente al numero di tuple dai processi di lavoro. Questo parametro stima i costi per lo scambio di dati.<\/p>\n<p><\/p>\n<h3 id=\"soedineniya-vlozhennyh-ciklov--nested-loop-join\">Join a ciclo nidificato \u2014 Nested Loop Join<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">PostgreSQL 9.6+ \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f.\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 '%special%deposits%'\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 !~~ '%special%deposits%'::text)<\/code><\/pre>\n<p><\/p>\n<p>La raccolta avviene nell'ultima fase, quindi il Nested Loop Left Join \u00e8 un'operazione parallela. Il Parallel Index Only Scan \u00e8 stato introdotto solo nella versione 10. Funziona in modo simile alla scansione sequenziale parallela. La condizione <code>c_custkey = o_custkey<\/code> legge un ordine per ogni riga cliente. Quindi non \u00e8 parallelo.<\/p>\n<p><\/p>\n<h3 id=\"hesh-soedinenie--hash-join\">Hash Join<\/h3>\n<p><\/p>\n<p>Ogni processo crea la propria tabella hash fino a PostgreSQL 11. E se ci sono pi\u00f9 di quattro processi, le prestazioni non miglioreranno. Nella nuova versione, la tabella hash \u00e8 condivisa. Ogni processo pu\u00f2 utilizzare WORK_MEM per creare la tabella hash.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">seleziona\n        l_shipmode,\n        somma(caso\n                quando o_orderpriority = '1-URGENT'\n                        o quando o_orderpriority = '2-HIGH'\n                        allora 1\n                altrimenti 0\n        fine) come high_line_count,\n        somma(caso\n                quando o_orderpriority &lt;&gt; '1-URGENT'\n                        e o_orderpriority &lt;&gt; '2-HIGH'\n                        allora 1\n                altrimenti 0\n        fine) come low_line_count\nda\n        ordini,\n        riga_articolo\ndove\n        o_orderkey = l_orderkey\n        e l_shipmode in ('MAIL', 'AIR')\n        e l_commitdate &lt; l_receiptdate\n        e l_shipdate &lt; l_commitdate\n        e l_receiptdate &gt;= data '1996-01-01'\n        e l_receiptdate &lt; data '1996-01-01' + intervallo '1' anno\ngruppo per\n        l_shipmode\nordine per\n        l_shipmode\nLIMIT 1;\n                                                                                                                                    PIANO QUERY\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n Limite  (costo=1964755.66..1964961.44 righe=1 larghezza=27) (tempo effettivo=7579.592..7922.997 righe=1 cicli=1)\n   -&gt;  Finalizza GroupAggregate  (costo=1964755.66..1966196.11 righe=7 larghezza=27) (tempo effettivo=7579.590..7579.591 righe=1 cicli=1)\n         Chiave di gruppo: lineitem.l_shipmode\n         -&gt;  Raccogli Merge  (costo=1964755.66..1966195.83 righe=28 larghezza=27) (tempo effettivo=7559.593..7922.319 righe=6 cicli=1)\n               Lavoratori pianificati: 4\n               Lavoratori lanciati: 4\n               -&gt;  Gruppo Parziale  (costo=1963755.61..1965192.44 righe=7 larghezza=27) (tempo effettivo=7548.103..7564.592 righe=2 cicli=5)\n                     Chiave di gruppo: lineitem.l_shipmode\n                     -&gt;  Ordina  (costo=1963755.61..1963935.20 righe=71838 larghezza=27) (tempo effettivo=7530.280..7539.688 righe=62519 cicli=5)\n                           Chiave di ordinamento: lineitem.l_shipmode\n                           Metodo di ordinamento: unione esterna  Disco: 2304kB\n                           Lavoratore 0:  Metodo di ordinamento: unione esterna  Disco: 2064kB\n                           Lavoratore 1:  Metodo di ordinamento: unione esterna  Disco: 2384kB\n                           Lavoratore 2:  Metodo di ordinamento: unione esterna  Disco: 2264kB\n                           Lavoratore 3:  Metodo di ordinamento: unione esterna  Disco: 2336kB\n                           -&gt;  Unione Hash Parallela  (costo=382571.01..1957960.99 righe=71838 larghezza=27) (tempo effettivo=7036.917..7499.692 righe=62519 cicli=5)\n                                 Condizione Hash: (lineitem.l_orderkey = orders.o_orderkey)\n                                 -&gt;  Scansione Sequenziale Parallela su lineitem  (costo=0.00..1552386.40 righe=71838 larghezza=19) (tempo effettivo=0.583..4901.063 righe=62519 cicli=5)\n                                       Filtro: ((l_shipmode = QUALSIASI ('{MAIL,AIR}'::bpchar[])) E (l_commitdate &lt; l_receiptdate) E (l_shipdate &lt; l_commitdate) E (l_receiptdate &gt;= '1996-01-01'::data) E (l_receiptdate &lt; '1997-01-01 00:00:00'::timestamp senza fuso orario))\n                                       Rigetti rimossi dal filtro: 11934691\n                                 -&gt;  Hash Parallelo  (costo=313722.45..313722.45 righe=3750045 larghezza=20) (tempo effettivo=2011.518..2011.518 righe=3000000 cicli=5)\n                                       Cestini: 65536  Batch: 256  Utilizzo di memoria: 3840kB\n                                       -&gt;  Scansione Sequenziale Parallela su ordini  (costo=0.00..313722.45 righe=3750045 larghezza=20) (tempo effettivo=0.029..995.948 righe=3000000 cicli=5)\n Tempo di pianificazione: 0.977 ms\n Tempo di esecuzione: 7923.770 ms<\/code><\/pre>\n<p><\/p>\n<p>La Query 12 di TPC-H illustra chiaramente una join hash parallela. Ogni processo lavora per creare una tabella hash comune.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-sliyaniem--merge-join\">Join per fusione \u2014 Merge Join<\/h3>\n<p><\/p>\n<p>La merge join \u00e8 intrinsecamente non parallela. Non preoccuparti se \u00e8 l'ultimo passaggio della query: pu\u00f2 comunque essere eseguita in parallelo.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">-- Query 2 da TPC-H\nspiega (costi esclusi) seleziona s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment\nda part, supplier, partsupp, nation, region\ndove\n        p_partkey = ps_partkey\n        e s_suppkey = ps_suppkey\n        e p_size = 36\n        e p_type simile a &#039;%BRASS&#039;\n        e s_nationkey = n_nationkey\n        e n_regionkey = r_regionkey\n        e r_name = &#039;AMERICA&#039;\n        e ps_supplycost = (\n                seleziona\n                        min(ps_supplycost)\n                da partsupp, supplier, nation, region\n                dove\n                        p_partkey = ps_partkey\n                        e s_suppkey = ps_suppkey\n                        e s_nationkey = n_nationkey\n                        e n_regionkey = r_regionkey\n                        e r_name = &#039;AMERICA&#039;\n        )\nordina per s_acctbal discendente, n_name, s_name, p_partkey\nLIMIT 100;\n                                                PIANO QUERY\n----------------------------------------------------------------------------------------------------------\n Limit\n   -&amp;gt;  Ordinamento\n         Chiave di Ordinamento: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey\n         -&amp;gt;  Merge Join\n               Condizione di Merge: (part.p_partkey = partsupp.ps_partkey)\n               Filtro di Join: (partsupp.ps_supplycost = (SubPlan 1))\n               -&amp;gt;  Raccolta Merge\n                     Lavoratori Pianificati: 4\n                     -&amp;gt;  Scansione Indice Parallelo usando &lt;strong&gt;part_pkey&lt;\/strong&gt; sulla parte\n                           Filtro: (((p_type)::text ~~ &#039;%BRASS&#039;::text) E (p_size = 36))\n               -&amp;gt;  Materializza\n                     -&amp;gt;  Ordina\n                           Chiave di ordinamento: partsupp.ps_partkey\n                           -&amp;gt;  Ciclo annidato\n                                 -&amp;gt;  Ciclo annidato\n                                       Filtro di join: (nation.n_regionkey = region.r_regionkey)\n                                       -&amp;gt;  Scansione sequenziale su region\n                                             Filtro: (r_name = &#039;AMERICA&#039;::bpchar)\n                                       -&amp;gt;  Join hash\n                                             Condizione hash: (supplier.s_nationkey = nation.n_nationkey)\n                                             -&amp;gt;  Scansione sequenziale su supplier\n                                             -&amp;gt;  Hash\n                                                   -&amp;gt;  Scansione sequenziale su nation\n                                 -&amp;gt;  Scansione indice utilizzando idx_partsupp_suppkey su partsupp\n                                       Condizione indice: (ps_suppkey = supplier.s_suppkey)\n               SottoPiano 1\n                 -&amp;gt;  Aggregare\n                       -&amp;gt;  Ciclo annidato\n                             Filtro di join: (nation_1.n_regionkey = region_1.r_regionkey)\n                             -&amp;gt;  Scansione sequenziale su region region_1\n                                   Filtro: (r_name = &#039;AMERICA&#039;::bpchar)\n                             -&amp;gt;  Ciclo annidato\n                                   -&amp;gt;  Ciclo annidato\n                                         -&amp;gt;  Scansione indice utilizzando idx_partsupp_partkey su partsupp partsupp_1\n                                               Condizione indice: (part.p_partkey = ps_partkey)\n                                         -&amp;gt;  Scansione indice utilizzando supplier_pkey su supplier supplier_1\n                                               Condizione indice: (s_suppkey = partsupp_1.ps_suppkey)\n                                   -&amp;gt;  Scansione indice utilizzando nation_pkey su nation nation_1\n                                         Condizione indice: (n_nationkey = supplier_1.s_nationkey)<\/code><\/pre>\n<p><\/p>\n<p>Il nodo \u00abMerge Join\u00bb si trova sopra \u00abGather Merge\u00bb. Pertanto, la fusione non utilizza l'elaborazione parallela. Tuttavia, il nodo \u00abParallel Index Scan\u00bb aiuta ancora con il segmento. <code>part_pkey<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-po-sekciyam\">Join per sezioni<\/h3>\n<p><\/p>\n<p>in PostgreSQL 11 <noindex><a rel=\"nofollow\" href=\"http:\/\/ashutoshpg.blogspot.com\/2017\/12\/partition-wise-joins-divide-and-conquer.html\">join per sezioni<\/a><\/noindex> \u00e8 disattivato per impostazione predefinita: ha una pianificazione molto costosa. Le tabelle con sezionamenti simili possono essere unite sezione per sezione. In questo modo, Postgres utilizzer\u00e0 tabelle hash pi\u00f9 piccole. Ogni join di sezioni pu\u00f2 essere parallelo.<\/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   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   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   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   Parallel Hash\n                     -&gt;  Parallel Seq Scan on prt1_p1 t1\n                           Filter: (b = 0)<\/code><\/pre>\n<p><\/p>\n<p>\u00c8 importante notare che la connessione per sezioni pu\u00f2 avvenire in parallelo solo se queste sezioni sono abbastanza grandi.<\/p>\n<p><\/p>\n<h3 id=\"parallelnoe-dopolnenie--parallel-append\">Appendice Parallelo \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> pu\u00f2 essere utilizzato al posto di diversi blocchi in vari flussi di lavoro. Questo \u00e8 comune con le query UNION ALL. Lo svantaggio \u00e8 una riduzione del parallelismo, poich\u00e9 ogni flusso di lavoro gestisce solo 1 query.<\/p>\n<p><\/p>\n<p>Sono stati avviati 2 flussi di lavoro, anche se sono stati attivati 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 &lt;= date &#039;2000-12-01&#039; - interval &#039;105&#039; day;\n                                           QUERY PLAN\n------------------------------------------------------------------------------------------------\n Gather\n   Workers Planned: 2\n   -&gt;  Parallel Append\n         -&gt;  Aggregate\n               -&gt;  Seq Scan on lineitem\n                     Filter: (l_shipdate &lt;= &#039;2000-08-18 00:00:00&#039;::timestamp without time zone)\n         -&gt;  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\">Le variabili pi\u00f9 importanti<\/h3>\n<p><\/p>\n<ul>\n<li>WORK_MEM limita la quantit\u00e0 di memoria per ogni processo, non solo per le query: work_mem <em> processi <\/em> collegamenti = molta memoria.<\/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 quanti flussi di lavoro utilizzer\u00e0 il programma per l'elaborazione parallela dal piano.<\/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 adatta il numero totale di flussi di lavoro in base al numero di core CPU nel server.<\/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 lo stesso, ma per processi di lavoro paralleli.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"itogi\">Risultati<\/h3>\n<p><\/p>\n<p>A partire dalla versione 9.6, l'elaborazione parallela pu\u00f2 migliorare notevolmente le prestazioni delle query complesse che scansionano molte righe o indici. In PostgreSQL 10, l'elaborazione parallela \u00e8 abilitata di default. Ricordate di disattivarla sui server con carichi di lavoro OLTP elevati. Le scansioni sequenziali o le scansioni degli indici consumano molte risorse. Se non state eseguendo un report su un intero set di dati, le query possono essere rese pi\u00f9 efficienti semplicemente aggiungendo gli indici mancanti o utilizzando una corretta partizionamento.<\/p>\n<p><\/p>\n<h3 id=\"ssylki\">Link<\/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\">Parallellismo in PostgreSQL 11<\/a><\/noindex><\/li>\n<\/ul>\n<p>Fonte: <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.0.1 - 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. \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\" \/>\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\/it\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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. \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\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/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\udd47Query parallele in PostgreSQL | ProHoster","description":"Nei moderni CPU ci sono molti core. Per anni, le applicazioni hanno inviato richieste ai database in parallelo. Se si tratta di una query di report su molte righe in una tabella, essa viene eseguita pi\u00f9 velocemente quando utilizza pi\u00f9 core, e in PostgreSQL \u00e8 possibile a partire dalla versione 9.6. Sono stati necessari 3 anni per implementare la funzione delle query parallele, con la necessit\u00e0 di riscrivere il codice in diverse fasi di esecuzione.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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. \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","og:url":"https:\/\/prohoster.info\/it\/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\/it\/wp-json\/wp\/v2\/posts\/30900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=30900"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/30900\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/22879"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=30900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=30900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=30900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}