{"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\/de\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","title":{"rendered":"Parallele Anfragen in PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Parallele Anfragen in PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/04\/bbb4b4d3f8714bbdb9b26ada2f2253b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nModerne CPUs verf\u00fcgen \u00fcber viele Kerne. \u00dcber Jahre hinweg haben Anwendungen parallel Datenbankanfragen gesendet. Bei einer Berichtsanfrage an viele Zeilen in einer Tabelle wird die Ausf\u00fchrung schneller, wenn mehrere CPUs genutzt werden, und in PostgreSQL ist dies ab Version 9.6 m\u00f6glich.<\/p>\n<p><\/p>\n<p>Es dauerte 3 Jahre, die Funktion f\u00fcr parallele Abfragen zu implementieren \u2014 der Code musste in verschiedenen Phasen der Abfrageausf\u00fchrung neu geschrieben werden. In PostgreSQL 9.6 wurde eine Infrastruktur zur weiteren Verbesserung des Codes eingef\u00fchrt. In sp\u00e4teren Versionen k\u00f6nnen auch andere Abfragetypen parallel ausgef\u00fchrt werden.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"ogranicheniya\">Einschr\u00e4nkungen<\/h3>\n<p><\/p>\n<ul>\n<li>Aktivieren Sie die parallele Ausf\u00fchrung nicht, wenn alle Kerne bereits belegt sind, da ansonsten andere Abfragen langsamer werden.<\/li>\n<li>Am wichtigsten ist, dass die parallele Verarbeitung mit hohen Werten f\u00fcr WORK_MEM viel Speicher beansprucht \u2014 jede Hash-Verbindung oder Sortierung ben\u00f6tigt Speicher in H\u00f6he von work_mem.<\/li>\n<li>OLTP-Anfragen mit niedriger Latenz k\u00f6nnen durch parallele Ausf\u00fchrung nicht beschleunigt werden. Wenn eine Anfrage nur eine Zeile zur\u00fcckgibt, wird die parallele Verarbeitung sie sogar verlangsamen.<\/li>\n<li>Entwickler nutzen gerne den TPC-H-Benchmark. Vielleicht haben Sie \u00e4hnliche Abfragen f\u00fcr eine optimale parallele Ausf\u00fchrung.<\/li>\n<li>Nur SELECT-Anfragen ohne pr\u00e4dikative Sperrung werden parallel ausgef\u00fchrt.<\/li>\n<li>Manchmal ist die richtige Indizierung besser als das sequenzielle Scannen der Tabelle im Parallelmodus.<\/li>\n<li>Anfragen und Cursor werden nicht unterst\u00fctzt.<\/li>\n<li>Fensterfunktionen und aggregierte Funktionen von geordneten Mengen sind nicht parallel.<\/li>\n<li>Sie gewinnen nichts bei der Eingabe-\/Ausgabebelastung.<\/li>\n<li>Es gibt keine parallelen Sortieralgorithmen. Aber Anfragen mit Sortierungen k\u00f6nnen in bestimmten Aspekten parallel ausgef\u00fchrt werden.<\/li>\n<li>Ersetzen Sie CTE (WITH \u2026) durch ein geschachteltes SELECT, um die parallele Verarbeitung zu erm\u00f6glichen.<\/li>\n<li>Datenwrapper von Drittanbietern unterst\u00fctzen bisher keine parallele Verarbeitung (k\u00f6nnten es aber!).<\/li>\n<li>FULL OUTER JOIN wird nicht unterst\u00fctzt.<\/li>\n<li>max_rows deaktiviert die parallele Verarbeitung.<\/li>\n<li>Wenn eine Funktion im Abfrage nicht als PARALLEL SAFE gekennzeichnet ist, wird sie einstr\u00e4ngig.<\/li>\n<li>Das Isolationsniveau der Transaktion SERIALIZABLE deaktiviert die parallele Verarbeitung.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"testovaya-sreda\">Testumgebung<\/h3>\n<p><\/p>\n<p>Die Entwickler von PostgreSQL haben versucht, die Reaktionszeit der TPC-H-Benchmarkabfragen zu verk\u00fcrzen. Laden Sie den Benchmark herunter und <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">passen Sie ihn an PostgreSQL an.<\/a><\/noindex>. Dies ist die inoffizielle Verwendung des TPC-H Benchmarks \u2014 nicht f\u00fcr den Vergleich von Datenbanken oder Hardware.<\/p>\n<p><\/p>\n<ol>\n<li>Laden Sie TPC-H_Tools_v2.17.3.zip (oder eine neuere Version) herunter <noindex><a rel=\"nofollow\" href=\"http:\/\/www.tpc.org\/tpc_documents_current_versions\/current_specifications.asp\">von der TPC-Website<\/a><\/noindex>.<\/li>\n<li>Benennen Sie makefile.suite in Makefile um und \u00e4ndern Sie es wie hier beschrieben: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/tvondra\/pg_tpch\">https:\/\/github.com\/tvondra\/pg_tpch <\/a><\/noindex>. Kompilieren Sie den Code mit dem Befehl make.<\/li>\n<li>Generieren Sie die Daten: <code>.\/dbgen -s 10<\/code> erstellt eine Datenbank von 23 GB. Das reicht aus, um den Unterschied in der Leistung zwischen parallelen und nicht-parallelen Abfragen zu sehen.<\/li>\n<li>Konvertieren Sie die Dateien <code>tbl<\/code> in <code>csv mit for<\/code> und <code>sed<\/code>.<\/li>\n<li>Klone das Repository <code>pg_tpch<\/code> und kopieren Sie die Dateien <code>csv<\/code> in <code>pg_tpch\/dss\/data<\/code>.<\/li>\n<li>Erstellen Sie die Abfragen mit dem Befehl <code>qgen<\/code>.<\/li>\n<li>Laden Sie die Daten in die Datenbank mit dem Befehl hoch <code>.\/tpch.sh<\/code>.<\/li>\n<\/ol>\n<p><\/p>\n<h3 id=\"parallelnoe-posledovatelnoe-skanirovanie\">Paralleles sequentielles Scannen<\/h3>\n<p><\/p>\n<p>Es k\u00f6nnte schneller sein, nicht aufgrund des parallelen Lesens, sondern weil die Daten \u00fcber viele CPU-Kerne verteilt sind. In modernen Betriebssystemen werden PostgreSQL-Datendateien gut zwischengespeichert. Mit vorab gelesenen Daten kann mehr aus dem Speicher abgerufen werden, als der PG-D\u00e4mon anfordert. Daher wird die Abfrageleistung nicht durch die Festplatten-I\/O limitiert. Sie ben\u00f6tigt CPU-Zyklen, um:<\/p>\n<p><\/p>\n<ul>\n<li>Zeilen einzeln von den Tabellen-Seiten zu lesen;<\/li>\n<li>Werte der Zeilen und Bedingungen zu vergleichen <code>WHERE<\/code>.<\/li>\n<\/ul>\n<p><\/p>\n<p>F\u00fchren wir eine einfache Abfrage durch <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>Ein sequentieller Scan liefert zu viele Zeilen ohne Aggregation, weshalb die Abfrage nur von einem CPU-Kern ausgef\u00fchrt wird.<\/p>\n<p><\/p>\n<p>Wenn Sie hinzuf\u00fcgen <code>SUM()<\/code>, wird deutlich, dass zwei Arbeitsprozesse helfen k\u00f6nnen, die Anfrage zu beschleunigen:<\/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\">Parallele Aggregation<\/h3>\n<p><\/p>\n<p>Der Knoten \u201eParallel Seq Scan\u201c erzeugt Zeilen f\u00fcr die partielle Aggregation. Der Knoten \u201ePartial Aggregate\u201c k\u00fcrzt diese Zeilen mit Hilfe von <code>SUM()<\/code>. Am Ende wird der SUM-Z\u00e4hler von jedem Arbeitsprozess vom Knoten \u201eGather\u201c zusammengetragen.<\/p>\n<p><\/p>\n<p>Das endg\u00fcltige Ergebnis wird vom Knoten \u201eFinalize Aggregate\u201c berechnet. Wenn Sie eigene Aggregationsfunktionen haben, vergessen Sie nicht, sie als \u201eparallel safe\u201c zu kennzeichnen.<\/p>\n<p><\/p>\n<h3 id=\"kolichestvo-rabochih-processov\">Anzahl der Arbeitsprozesse<\/h3>\n<p><\/p>\n<p>Die Anzahl der Arbeitsprozesse kann ohne einen Neustart des Servers erh\u00f6ht werden:<\/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>Was passiert hier? Die Anzahl der Arbeitsprozesse hat sich verdoppelt, und die Anfrage wurde nur um das 1,6599-fache schneller. Die Berechnungen sind interessant. Wir hatten 2 Arbeitsprozesse und 1 F\u00fchrungsprozess. Nach der \u00c4nderung wurde es 4+1.<\/p>\n<p><\/p>\n<p>Unsere maximale Beschleunigung durch parallele Verarbeitung: 5\/3 = 1,66(6) mal.<\/p>\n<p><\/p>\n<h2 id=\"kak-eto-rabotaet\">Wie funktioniert das?<\/h2>\n<p><\/p>\n<h3 id=\"processy\">Prozesse<\/h3>\n<p><\/p>\n<p>Die Ausf\u00fchrung einer Anfrage beginnt immer mit dem f\u00fchrenden Prozess. Der F\u00fchrungsprozess erledigt alles Nicht-Parallele und einen Teil der parallelen Verarbeitung. Die anderen Prozesse, die dieselben Anfragen bearbeiten, werden Arbeitsprozesse genannt. Die parallele Verarbeitung nutzt die Infrastruktur von <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/11\/bgworker.html\">dynamischen Hintergrundarbeitsprozessen<\/a><\/noindex> (ab Version 9.4). Da andere Teile von PostgreSQL Prozesse anstelle von Threads verwenden, kann eine Anfrage mit 3 Arbeitern bis zu 4 Mal schneller sein als die traditionelle Verarbeitung.<\/p>\n<p><\/p>\n<h3 id=\"vzaimodeystvie\">Interaktion<\/h3>\n<p><\/p>\n<p>Die Arbeiter kommunizieren mit dem Leader \u00fcber eine Nachrichtenwarteschlange (auf Basis gemeinsamer Speicher). Jeder Prozess hat 2 Warteschlangen: eine f\u00fcr Fehler und eine f\u00fcr Tupel.<\/p>\n<p><\/p>\n<h3 id=\"skolko-nuzhno-rabochih-processov\">Wie viele Arbeiter werden ben\u00f6tigt?<\/h3>\n<p><\/p>\n<p>Die Mindestgrenze wird durch den Parameter <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>festgelegt. Dann nimmt der Abfrageausf\u00fchrer Arbeiter aus dem Pool, der durch den Parameter <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>begrenzt ist. Die letzte Grenze ist <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>, also die Gesamtzahl der Hintergrundprozesse.<\/p>\n<p><\/p>\n<p>Wenn kein Arbeiter zugeordnet werden kann, erfolgt die Verarbeitung mit einem einzelnen Prozess.<\/p>\n<p><\/p>\n<p>Der Abfrageplaner kann die Arbeiter je nach Gr\u00f6\u00dfe der Tabelle oder des Indexes reduzieren. Daf\u00fcr gibt es die Parameter <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> und <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 Tabelle =&gt; 1 Arbeiter\n24MB Tabelle =&gt; 2 Arbeiter\n72MB Tabelle =&gt; 3 Arbeiter\nx =&gt; log(x \/ min_parallel_table_scan_size) \/ log(3) + 1 Arbeiter<\/code><\/pre>\n<p><\/p>\n<p>Jedes Mal, wenn die Tabelle 3 Mal gr\u00f6\u00dfer ist als <code>min_parallel_(index|table)_scan_size<\/code>, Postgres f\u00fcgt einen Arbeitsprozess hinzu. Die Anzahl der Arbeitsprozesse basiert nicht auf den Kosten. Zirkul\u00e4re Abh\u00e4ngigkeiten erschweren komplexe Implementierungen. Stattdessen verwendet der Planner einfache Regeln.<\/p>\n<p><\/p>\n<p>In der Praxis sind diese Regeln nicht immer f\u00fcr die Produktion geeignet, sodass Sie die Anzahl der Arbeitsprozesse f\u00fcr eine bestimmte Tabelle \u00e4ndern k\u00f6nnen: ALTER TABLE \u2026 SET (<code>parallel_workers = N<\/code>).<\/p>\n<p><\/p>\n<h3 id=\"pochemu-parallelnaya-obrabotka-ne-ispolzuetsya\">Warum wird die parallele Verarbeitung nicht verwendet?<\/h3>\n<p><\/p>\n<p>Neben einer langen Liste von Einschr\u00e4nkungen gibt es auch Kosten\u00fcberpr\u00fcfungen:<\/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 um auf parallele Verarbeitung kurzer Abfragen zu verzichten. Dieser Parameter sch\u00e4tzt die Zeit zum Vorbereiten des Speichers, zum Starten des Prozesses und zum ersten Datenaustausch.<\/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>: Die Kommunikation zwischen dem Leader und den Arbeitsprozessen kann proportional zur Anzahl der Tupel von den Arbeitsprozessen verz\u00f6gert werden. Dieser Parameter berechnet die Kosten f\u00fcr den Datenaustausch.<\/p>\n<p><\/p>\n<h3 id=\"soedineniya-vlozhennyh-ciklov--nested-loop-join\">Verschachtelte Schleifenverkn\u00fcpfungen \u2014 Nested Loop Join<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">PostgreSQL 9.6+ kann verschachtelte Schleifen parallel ausf\u00fchren \u2013 das ist eine einfache 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>Die Zusammenf\u00fchrung erfolgt in der letzten Phase, sodass der Nested Loop Left Join eine parallele Operation ist. Der Parallel Index Only Scan wurde erst in Version 10 eingef\u00fchrt. Er funktioniert \u00e4hnlich wie der parallele sequentielle Scan. Bedingung <code>c_custkey = o_custkey<\/code> liest eine Bestellung f\u00fcr jede Kundenzeile. Daher ist es nicht parallel.<\/p>\n<p><\/p>\n<h3 id=\"hesh-soedinenie--hash-join\">Hash Join<\/h3>\n<p><\/p>\n<p>Jeder Arbeitsprozess erstellt seine eigene Hash-Tabelle bis PostgreSQL 11. Wenn es mehr als vier dieser Prozesse gibt, wird die Leistung nicht gesteigert. In der neuen Version ist die Hash-Tabelle gemeinsam. Jeder Arbeitsprozess kann WORK_MEM nutzen, um eine Hash-Tabelle zu erstellen.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">w\u00e4hlen\n        l_shipmode,\n        sum(case\n                when o_orderpriority = '1-URGENT'\n                        or o_orderpriority = '2-HIGH'\n                        dann 1\n                sonst 0\n        end) as high_line_count,\n        sum(case\n                when o_orderpriority &lt;&gt; '1-URGENT'\n                        und o_orderpriority &lt;&gt; '2-HIGH'\n                        dann 1\n                sonst 0\n        end) as low_line_count\nfrom\n        orders,\n        lineitem\nwhere\n        o_orderkey = l_orderkey\n        und l_shipmode in ('MAIL', 'AIR')\n        und l_commitdate &lt; l_receiptdate\n        und l_shipdate &lt; l_commitdate\n        und l_receiptdate &gt;= date '1996-01-01'\n        und l_receiptdate &lt; date '1996-01-01' + interval '1' year\ngroup by\n        l_shipmode\norder by\n        l_shipmode\nLIMIT 1;\n                                                                                                                                    QUERY PLAN\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n Limit  (cost=1964755.66..1964961.44 rows=1 width=27) (actual time=7579.592..7922.997 rows=1 loops=1)\n   -&gt;  Finalize GroupAggregate  (cost=1964755.66..1966196.11 rows=7 width=27) (actual time=7579.590..7579.591 rows=1 loops=1)\n         Group Key: lineitem.l_shipmode\n         -&gt;  Gather Merge  (cost=1964755.66..1966195.83 rows=28 width=27) (actual time=7559.593..7922.319 rows=6 loops=1)\n               Workers Planned: 4\n               Workers Launched: 4\n               -&gt;  Partial GroupAggregate  (cost=1963755.61..1965192.44 rows=7 width=27) (actual time=7548.103..7564.592 rows=2 loops=5)\n                     Group Key: lineitem.l_shipmode\n                     -&gt;  Sort  (cost=1963755.61..1963935.20 rows=71838 width=27) (actual time=7530.280..7539.688 rows=62519 loops=5)\n                           Sort Key: lineitem.l_shipmode\n                           Sort Method: external merge  Disk: 2304kB\n                           Worker 0:  Sort Method: external merge  Disk: 2064kB\n                           Worker 1:  Sort Method: external merge  Disk: 2384kB\n                           Worker 2:  Sort Method: external merge  Disk: 2264kB\n                           Worker 3:  Sort Method: external merge  Disk: 2336kB\n                           -&gt;  Parallel Hash Join  (cost=382571.01..1957960.99 rows=71838 width=27) (actual time=7036.917..7499.692 rows=62519 loops=5)\n                                 Hash Cond: (lineitem.l_orderkey = orders.o_orderkey)\n                                 -&gt;  Parallel Seq Scan on lineitem  (cost=0.00..1552386.40 rows=71838 width=19) (actual time=0.583..4901.063 rows=62519 loops=5)\n                                       Filter: ((l_shipmode = ANY ('{MAIL,AIR}'::bpchar[])) AND (l_commitdate &lt; l_receiptdate) AND (l_shipdate &lt; l_commitdate) AND (l_receiptdate &gt;= '1996-01-01'::date) AND (l_receiptdate &lt; '1997-01-01 00:00:00'::timestamp without time zone))\n                                       Rows Removed by Filter: 11934691\n                                 -&gt;  Parallel Hash  (cost=313722.45..313722.45 rows=3750045 width=20) (actual time=2011.518..2011.518 rows=3000000 loops=5)\n                                       Buckets: 65536  Batches: 256  Memory Usage: 3840kB\n                                       -&gt;  Parallel Seq Scan on orders  (cost=0.00..313722.45 rows=3750045 width=20) (actual time=0.029..995.948 rows=3000000 loops=5)\n Planning Time: 0.977 ms\n Execution Time: 7923.770 ms<\/code><\/pre>\n<p><\/p>\n<p>Die Anfrage 12 aus TPC-H zeigt anschaulich eine parallele Hash-Verkn\u00fcpfung. Jeder Workprozess tr\u00e4gt zur Erstellung einer gemeinsamen Hash-Tabelle bei.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-sliyaniem--merge-join\">Merge Join<\/h3>\n<p><\/p>\n<p>Ein Merge Join ist grunds\u00e4tzlich nicht parallel. Machen Sie sich keine Sorgen, wenn dies die letzte Phase der Anfrage ist \u2013 sie kann dennoch parallel ausgef\u00fchrt werden.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">-- Abfrage 2 aus TPC-H\nErkl&auml;rung (Kosten aus)\nW&auml;hlen Sie s_acctbal, s_name, n_name, p_partkey, p_mfgr, s_address, s_phone, s_comment\nvon Teil, Lieferant, partsupp, Nation, Region\nwo\n        p_partkey = ps_partkey\n        und s_suppkey = ps_suppkey\n        und p_size = 36\n        und p_type wie &#039;%BRASS&#039;\n        und s_nationkey = n_nationkey\n        und n_regionkey = r_regionkey\n        und r_name = &#039;AMERIKA&#039;\n        und ps_supplycost = (\n                w&auml;hlen\n                        min(ps_supplycost)\n                von partsupp, Lieferant, Nation, Region\n                wo\n                        p_partkey = ps_partkey\n                        und s_suppkey = ps_suppkey\n                        und s_nationkey = n_nationkey\n                        und n_regionkey = r_regionkey\n                        und r_name = &#039;AMERIKA&#039;\n        )\nbestellen nach s_acctbal absteigend, n_name, s_name, p_partkey\nLIMIT 100;\n                                                ABFRAGEPLAN\n----------------------------------------------------------------------------------------------------------\n Limit\n   -&amp;gt;  Sortieren\n         Sortierschl&uuml;ssel: supplier.s_acctbal DESC, nation.n_name, supplier.s_name, part.p_partkey\n         -&amp;gt;  Merge Join\n               Merge-Bedingung: (part.p_partkey = partsupp.ps_partkey)\n               Join-Filter: (partsupp.ps_supplycost = (SubPlan 1))\n               -&amp;gt;  Gather Merge\n                     Geplante Arbeiter: 4\n                     -&amp;gt;  Paralleler Index-Scan unter Verwendung von &lt;strong&gt;part_pkey&lt;\/strong&gt; auf Teil\n                           Filter: (((p_type)::text ~~ &#039;%BRASS&#039;::text) UND (p_size = 36))\n               -&amp;gt;  Materialisiere\n                     -&amp;gt;  Sortieren\n                           Sortierschl&uuml;ssel: partsupp.ps_partkey\n                           -&amp;gt;  Verschachtelter Loop\n                                 -&amp;gt;  Verschachtelter Loop\n                                       Join-Filter: (nation.n_regionkey = region.r_regionkey)\n                                       -&amp;gt;  Seq Scan auf region\n                                             Filter: (r_name = &#039;AMERICA&#039;::bpchar)\n                                       -&amp;gt;  Hash Join\n                                             Hash-Bedingung: (supplier.s_nationkey = nation.n_nationkey)\n                                             -&amp;gt;  Seq Scan auf supplier\n                                             -&amp;gt;  Hash\n                                                   -&amp;gt;  Seq Scan auf nation\n                                 -&amp;gt;  Index Scan unter Verwendung von idx_partsupp_suppkey auf partsupp\n                                       Index-Bedingung: (ps_suppkey = supplier.s_suppkey)\n               Teilplan 1\n                 -&amp;gt;  Aggregat\n                       -&amp;gt;  Verschachtelter Loop\n                             Join-Filter: (nation_1.n_regionkey = region_1.r_regionkey)\n                             -&amp;gt;  Seq Scan auf region region_1\n                                   Filter: (r_name = &#039;AMERICA&#039;::bpchar)\n                             -&amp;gt;  Verschachtelter Loop\n                                   -&amp;gt;  Verschachtelter Loop\n                                         -&amp;gt;  Index Scan unter Verwendung von idx_partsupp_partkey auf partsupp partsupp_1\n                                               Index-Bedingung: (part.p_partkey = ps_partkey)\n                                         -&amp;gt;  Index Scan unter Verwendung von supplier_pkey auf supplier supplier_1\n                                               Index-Bedingung: (s_suppkey = partsupp_1.ps_suppkey)\n                                   -&amp;gt;  Index Scan unter Verwendung von nation_pkey auf nation nation_1\n                                         Index-Bedingung: (n_nationkey = supplier_1.s_nationkey)<\/code><\/pre>\n<p><\/p>\n<p>Der Knoten \u201eMerge Join\u201c befindet sich \u00fcber dem \u201eGather Merge\u201c. Daher nutzt das Merging keine parallele Verarbeitung. Aber der Knoten \u201eParallel Index Scan\u201c hilft dennoch im Segment. <code>part_pkey<\/code>.<\/p>\n<p><\/p>\n<h3 id=\"soedinenie-po-sekciyam\">Partition Join<\/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\">Partition Join<\/a><\/noindex> ist standardm\u00e4\u00dfig deaktiviert, da es sehr kostenintensive Planungen erfordert. Tabellen mit \u00e4hnlicher Partitionierung k\u00f6nnen Abschnitt f\u00fcr Abschnitt verkn\u00fcpft werden. So verwendet Postgres kleinere Hash-Tabellen. Jede Verkn\u00fcpfung der Partitionen kann parallel sein.<\/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>Das wichtigste ist, dass die Partitionierungsverbindungen nur dann parallel sind, wenn diese Partitionen ausreichend gro\u00df sind.<\/p>\n<p><\/p>\n<h3 id=\"parallelnoe-dopolnenie--parallel-append\">Paralleler Anhang \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> kann anstelle verschiedener Bl\u00f6cke in unterschiedlichen Arbeitsabl\u00e4ufen verwendet werden. Dies geschieht h\u00e4ufig bei UNION ALL-Anfragen. Nachteil ist weniger Parallelit\u00e4t, da jeder Arbeitsablauf nur eine Anfrage bearbeitet.<\/p>\n<p><\/p>\n<p>Hier sind 2 Arbeitsabl\u00e4ufe gestartet, obwohl 4 aktiviert sind.<\/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   Paralleler Anhang\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\">Die wichtigsten Variablen<\/h3>\n<p><\/p>\n<ul>\n<li>WORK_MEM begrenzt den Speicher f\u00fcr jeden Prozess, nicht nur f\u00fcr Anfragen: work_mem <em> Prozesse <\/em> Verbindungen = sehr viel Speicher.<\/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 wie viele Arbeitsabl\u00e4ufe das ausf\u00fchrende Programm f\u00fcr die parallele Verarbeitung gem\u00e4\u00df dem Plan verwenden wird.<\/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 passt die Gesamtl\u00e4nge der Arbeitsabl\u00e4ufe an die Anzahl der CPU-Kerne im Server an.<\/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 das Gleiche, aber f\u00fcr parallele Arbeitsprozesse.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"itogi\">Ergebnisse<\/h3>\n<p><\/p>\n<p>Seit Version 9.6 kann die parallele Verarbeitung die Leistung komplexer Abfragen deutlich verbessern, die viele Zeilen oder Indizes scannen. In PostgreSQL 10 ist die parallele Verarbeitung standardm\u00e4\u00dfig aktiviert. Denken Sie daran, sie auf Servern mit hoher OLTP-Last zu deaktivieren. Sequentielle Scans oder das Scannen von Indizes verbrauchen sehr viele Ressourcen. Wenn Sie keinen Bericht \u00fcber den gesamten Datensatz erstellen, k\u00f6nnen Abfragen produktiver gestaltet werden, indem einfach fehlende Indizes hinzugef\u00fcgt oder die richtige Partitionierung verwendet wird.<\/p>\n<p><\/p>\n<h3 id=\"ssylki\">Links<\/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\">Parallelismus in PostgreSQL 11<\/a><\/noindex><\/li>\n<\/ul>\n<p>Quelle: <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 4.9.10 - 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\/de\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47Parallele Abfragen in PostgreSQL | ProHoster","description":"Moderne CPUs verf\u00fcgen \u00fcber viele Kerne. \u00dcber Jahre hinweg senden Anwendungen Anfragen parallel an Datenbanken. Wenn es sich um eine Berichtsanfrage f\u00fcr viele Zeilen in einer Tabelle handelt, wird sie schneller ausgef\u00fchrt, wenn mehrere CPUs aktiviert sind, und das ist in PostgreSQL ab Version 9.6 m\u00f6glich. Es dauerte 3 Jahre, diese Funktion f\u00fcr parallele Abfragen zu implementieren \u2014 der Code musste in verschiedenen Ausf\u00fchrungsschritten neu geschrieben werden.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/parallelnye-zaprosy-v-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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\/de\/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"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=30900"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30900\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/22879"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=30900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=30900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=30900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}