

 Amazon Redshift unterstützt UDFs ab Patch 198 nicht mehr die Erstellung von neuem Python. Das bestehende Python UDFs wird bis zum 30. Juni 2026 weiterhin funktionieren. Weitere Informationen finden Sie im [Blog-Posting](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/). 

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Datenverteilung zur Abfrageoptimierung
<a name="t_Distributing_data"></a>

Wenn Sie Daten in eine Tabelle laden, verteilt Amazon Redshift die Zeilen der Tabelle entsprechend dem Verteilungsstil der Tabelle an die einzelnen Datenverarbeitungsknoten. Wenn sie eine Abfrage ausführen, führt der Abfrageoptimierer nach Bedarf eine Neuverteilung der Zeilen zu den Datenverarbeitungsknoten durch, um Join- oder Aggregierungsoperationen durchführen zu können. Das Ziel der Auswahl eines Tabellenverteilungsstils besteht darin, die Auswirkungen des Neuverteilungsschritts dadurch zu minimieren, dass die Daten dort platziert sind, wo sie benötigt werden, bevor die Abfrage ausgeführt wird.

**Anmerkung**  
In diesem Abschnitt werden die Grundsätze der Datenverteilung in einer Amazon-Redshift-Datenbank vorgestellt. Wir empfehlen, Ihre Tabellen mit `DISTSTYLE AUTO` zu erstellen. Wenn Sie dies tun, verwendet Amazon Redshift die automatische Tabellenoptimierung, um den Datenverteilungsstil auszuwählen. Weitere Informationen finden Sie unter [Aktivieren automatischer Tabellenoptimierung](t_Creating_tables.md). Der Rest dieses Abschnitts enthält Details zu Verteilungsstilen. 

**Topics**
+ [Datenverteilungskonzepte](#t_data_distribution_concepts)
+ [Verteilungsstile](c_choosing_dist_sort.md)
+ [Anzeigen von Verteilungsstilen](viewing-distribution-styles.md)
+ [Auswerten von Abfragemustern](t_evaluating_query_patterns.md)
+ [Bezeichnen von Verteilungsstilen](t_designating_distribution_styles.md)
+ [Auswerten des Abfrageplans](c_data_redistribution.md)
+ [Beispiel für einen Abfrageplan](t_explain_plan_example.md)
+ [Verteilungsbeispiele](c_Distribution_examples.md)

## Datenverteilungskonzepte
<a name="t_data_distribution_concepts"></a>

Einige Datenverteilungskonzepte für Amazon Redshift folgen.

 **Knoten und Slices** 

 Ein Amazon-Redshift-Cluster besteht aus einem Satz von Knoten. Jeder Knoten im Cluster besitzt ein eigenes Betriebssystem, einen eigenen dedizierten Arbeitsspeicher und einen eigenen dedizierten Datenträgerplatz. Ein Knoten ist der *Führungsknoten*, der die Verteilung von Daten- und Abfrageverarbeitungsaufgaben an die Datenverarbeitungsknoten verwaltet. Die *Datenverarbeitungsknoten* stellen Ressourcen bereit, um diese Aufgaben zu erledigen. 

 Der Datenträgerplatz für einen Datenverarbeitungsknoten ist in verschiedene *Slices* aufgeteilt. Die Anzahl der Slices pro Knoten ist von der Knotengröße des Clusters abhängig. Die Knoten sind alle an der parallelen Abfrageausführung beteiligt und arbeiten mit Daten, die so gleichmäßig wie möglich über die Slices verteilt sind. Weitere Informationen zur Anzahl der Slices für die einzelnen Knotengrößen finden Sie unter [About Clusters and Nodes](https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#rs-about-clusters-and-nodes) (Informationen zu Clustern und Knoten) im *Amazon-Redshift-Verwaltungshandbuch*.

 **Datenumverteilung** 

 Wenn Sie Daten in eine Tabelle laden, verteilt Amazon Redshift die Zeilen der Tabelle entsprechend dem Verteilungsstil der Tabelle an die einzelnen Knoten-Slices. Als Teil des Abfrageplans ermittelt der Optimierer die Stellen, an denen die Datenblöcke platziert werden müssen, um die Abfrage optimal ausführen zu können. Die Daten werden anschließend während der Ausführung der Abfrage physisch verschoben bzw. umverteilt. Während der Umverteilung können einzelne Zeilen an Knoten gesendet werden, um einen Join auszuführen, oder eine ganze Tabelle an alle Knoten gesendet werden. 

 Die Datenumverteilung kann einen wesentlichen Anteil an den Kosten eines Abfrageplans haben und der generierte Netzwerkdatenverkehr kann sich auf andere Datenbankoperationen auswirken und die Systemleistung insgesamt beeinträchtigen. Wenn Sie bereits zu Beginn überlegen, wo die Daten am besten platziert werden sollten, können Sie die Auswirkungen der Datenumverteilung minimieren. 

 **Ziele der Datenverteilung** 

 Wenn Sie Daten in eine Tabelle laden, verteilt Amazon Redshift die Zeilen der Tabelle entsprechend dem Verteilungsstil, den Sie während der Erstellung der Tabelle gewählt haben, an die Datenverarbeitungsknoten und Slices. Die Datenverteilung hat zwei primäre Ziele: 
+ Gleichmäßige Verteilung des Workloads auf die Knoten im Cluster. Eine ungleichmäßige Verteilung oder Verteilungsverzerrung zwingt einige Knoten, mehr Arbeit zu leisten als andere, was die Abfrageleistung beeinträchtigt.
+ Minimierung der Datenverschiebungen während einer Abfrage. Wenn die Zeilen, die an Joins oder Aggregationen beteiligt sind, auf den Knoten bereits zusammen mit den entsprechenden Join-Zeilen in anderen Tabellen platziert werden, muss der Optimierer während der Abfrage weniger Daten umverteilen.

Die von Ihnen für Ihre Datenbank gewählte Verteilungsstrategie hat wichtige Folgen für die Abfrageleistung, die Speicheranforderungen, das Laden von Daten und die Wartung. Indem Sie für jede Tabelle den optimalen Verteilungsstil auswählen, können Sie Ihre Daten gleichmäßig verteilen und die allgemeine Systemleistung deutlich verbessern.

# Verteilungsstile
<a name="c_choosing_dist_sort"></a>

Wenn Sie eine Tabelle erstellen, können Sie einen von vier Verteilungsstilen angeben, AUTO, EVEN, KEY oder ALL. 

Falls Sie keinen Verteilungsstil angeben, verwendet Amazon Redshift die AUTO-Verteilung.

 **AUTO-Verteilung** 

Bei der AUTO-Verteilung weist Amazon Redshift auf der Grundlage der Größe der Tabellendaten den optimalen Verteilungsstil aus. Wenn beispielsweise der Verteilungsstil AUTO angegeben ist, weist Amazon Redshift kleinen Tabellen zunächst den Verteilungsstil ALL zu. Wenn die Tabelle größer wird, ändert Amazon Redshift den Verteilungsstil möglicherweise in KEY und wählt den Primärschlüssel (oder eine Spalte des zusammengesetzten Primärschlüssels) als Verteilungsschlüssel. Wenn die Tabelle größer wird und keine der Spalten als Verteilungsschlüssel geeignet ist, ändert Amazon Redshift den Verteilungsstil in EVEN. Die Änderung des Verteilungsstils erfolgt im Hintergrund mit minimalen Auswirkungen auf die Benutzerabfragen. 

Informationen zum Anzeigen von Aktionen, die Amazon Redshift automatisch zum Ändern eines Tabellenverteilungsschlüssels ausgeführt hat, finden Sie unter [SVL\$1AUTO\$1WORKER\$1ACTION](r_SVL_AUTO_WORKER_ACTION.md). Informationen zum Anzeigen aktueller Empfehlungen zum Ändern eines Tabellenverteilungsschlüssels finden Sie unter [SVV\$1ALTER\$1TABLE\$1RECOMMENDATIONS](r_SVV_ALTER_TABLE_RECOMMENDATIONS.md). 

Um den Verteilungsstil einer Tabelle anzuzeigen, führen Sie eine Abfrage für die Systemkatalogansicht PG\$1CLASS\$1INFO aus. Weitere Informationen finden Sie unter [Anzeigen von Verteilungsstilen](viewing-distribution-styles.md). Falls Sie die CREATE TABLE-Anweisung ohne Verteilungsstil angeben, verwendet Amazon Redshift die AUTO-Verteilung. 

 **EVEN-Verteilung** 

 Der Führungsknoten verteilt die Zeilen nacheinander über die Slices, unabhängig von den Werten in einer bestimmten Spalte. EVEN-Verteilung ist angemessen, wenn eine Tabelle nicht an Joins beteiligt ist. Sie ist auch angemessen, wenn keine klare Entscheidung zwischen der KEY-Verteilung und der ALL-Verteilung getroffen werden kann.

 **KEY-Verteilung** 

 Die Zeilen werden entsprechend den Werten in einer einzelnen Spalte verteilt. Der Führungsknoten platziert übereinstimmende Werte auf demselben Knoten-Slice. Wenn Sie ein Paar von Tabellen anhand der Joining-Schlüssel verteilen, platziert der Führungsknoten entsprechend den Werten in den Joining-Spalten die Zeilen in den Slices. Auf diese Weise werden übereinstimmende Werte aus den gemeinsamen Spalten physisch zusammen gespeichert. 

 **ALL-Verteilung** 

 An jeden Knoten wird eine Kopie der gesamten Tabelle verteilt. Während die EVEN-Verteilung oder die KEY-Verteilung nur einen Teil der Zeilen einer Tabelle auf den einzelnen Knoten platzieren, stellt die ALL-Verteilung sicher, dass alle Zeilen für alle Joins, an denen die Tabelle beteiligt ist, gemeinsam gespeichert werden. 

 Die ALL-Verteilung multipliziert den erforderlichen Speicherplatz mit der Zahl der Knoten im Cluster. Daher dauert es sehr viel länger, Daten zu laden, zu aktualisieren oder in mehrere Tabellen einzufügen. Die ALL-Verteilung ist nur für Tabellen geeignet, die sich vergleichsweise wenig verändern, d. h. Tabellen, die nicht häufig oder umfassend aktualisiert werden. Da die Kosten für die Umverteilung kleiner Tabellen während einer Abfrage gering sind, gibt es keinen signifikanten Vorteil, kleine Dimensionstabellen als DISTSTYLE ALL zu definieren. 

**Anmerkung**  
 Nachdem Sie für eine Spalte einen Verteilungsstil angegeben haben, verarbeitet Amazon Redshift die Datenverteilung auf Cluster-Ebene. Amazon Redshift erfordert keine Partitionierung von Daten innerhalb von Datenbankobjekten oder unterstützt dieses Konzept. Sie müssen keine Tabellenräume erstellen oder Partitionierungsschemen für Tabellen definieren. 

In bestimmten Szenarien können Sie den Verteilungsstil einer Tabelle nach der Erstellung ändern. Weitere Informationen finden Sie unter [ALTER TABLE](r_ALTER_TABLE.md). In Szenarien, in denen Sie den Verteilungsstil nach der Erstellung nicht ändern können, können Sie die Tabelle neu erstellen und die neue Tabelle mit einer Deep Copy-Operation füllen. Weitere Informationen finden Sie unter [Ausführen einer Deep Copy-Operation](performing-a-deep-copy.md)

# Anzeigen von Verteilungsstilen
<a name="viewing-distribution-styles"></a>

Um den Verteilungsstil einer Tabelle anzuzeigen, führen Sie eine Abfrage für die Systemkatalogansichten PG\$1CLASS\$1INFO oder SVV\$1TABLE\$1INFO aus.

Die Spalte RELEFFECTIVEDISTSTYLE in PG\$1CLASS\$1INFO zeigt den Verteilungsstil für die Tabelle an. Wenn die Tabelle die automatische Verteilung verwendet, ist RELEFFECTIVEDISTSTYLE auf 10, 11 oder 12 festgelegt. Diese Werte bezeichnen die verwendeten Verteilungsstile AUTO (ALL), AUTO (EVEN) oder AUTO (KEY). Wenn die Tabelle die automatische Verteilung verwendet, ändert sich der Verteilungsstile von anfänglich AUTO (ALL) in AUTO (EVEN) oder AUTO (KEY), wenn die Tabelle wächst. 

In der folgenden Tabelle wird der Verteilungsstil für die einzelnen Werte in der Spalte RELEFFECTIVEDISTSTYLE angegeben: 


| RELEFFECTIVEDISTSTYLE | Aktueller Verteilungsstil | 
| --- | --- | 
| 0 | EVEN | 
| 1 | KEY | 
| 8 | ALL | 
| 10 | AUTO (ALL) | 
| 11 | AUTO (EVEN) | 
| 12 | AUTO (KEY) | 

Die Spalte DISTSTYLE in SVV\$1TABLE\$1INFO zeigt den aktuellen Verteilungsstil für die Tabelle an. Wenn die Tabelle die automatische Verteilung verwendet, ist für DISTSTYLE entweder AUTO (ALL), AUTO (EVEN) oder AUTO (KEY) festgelegt.

Im folgenden Beispiel werden vier Tabellen erstellt, die die drei Verteilungsstile und die automatische Verteilung verwenden, anschließend wird eine Abfrage für PG\$1TABLE\$1INFO ausgeführt, um die Verteilungsstile anzuzeigen. 

```
create table public.dist_key (col1 int)
diststyle key distkey (col1);

insert into public.dist_key values (1);

create table public.dist_even (col1 int)
diststyle even;

insert into public.dist_even values (1);

create table public.dist_all (col1 int)
diststyle all;

insert into public.dist_all values (1);

create table public.dist_auto (col1 int);

insert into public.dist_auto values (1);

select "schema", "table", diststyle from SVV_TABLE_INFO
where "table" like 'dist%';

        schema   |    table        | diststyle
     ------------+-----------------+------------
      public     | dist_key        | KEY(col1)
      public     | dist_even       | EVEN
      public     | dist_all        | ALL
      public     | dist_auto       | AUTO(ALL)
```

# Auswerten von Abfragemustern
<a name="t_evaluating_query_patterns"></a>

 Die Wahl des Verteilungsstils stellt nur einen Aspekt des Datenbankdesigns dar. Betrachten Sie den Verteilungsstil im Kontext des gesamten Systems und wägen Sie die Verteilung mit anderen wichtigen Faktoren wie Clustergröße, Methoden der Kompressionskodierung, Sortierschlüsseln und Tabelleneinschränkungen ab. 

 Testen Sie Ihr System mit Daten, die so nahe an den realen Daten wie möglich sind. 

Um eine gute Wahl in Bezug auf den Verteilungsstil treffen zu können, müssen Sie die Abfragemuster für Ihre Amazon-Redshift-Anwendung verstehen. Identifizieren Sie aufwändigsten Abfragen in Ihrem System und bauen Sie bei Ihrem anfänglichen Datenbankdesign auf den Anforderungen dieser Abfragen auf. Zu den Faktoren, die die Gesamtkosten einer Abfrage bestimmen, gehören die Dauer der Ausführung der Abfrage und die Zahl der beanspruchten Datenverarbeitungsressourcen. Andere Faktoren, die die Abfragekosten bestimmen, sind die Häufigkeit der Ausführung und die Unterbrechung anderer Abfragen und Datenbankvorgänge. 

 Identifizieren Sie die Tabellen, die von den kostenintensivsten Abfragen verwendet werden, und werten sie deren Rolle bei der Abfragelaufzeit aus. Betrachten Sie die Joins und Aggregationen für diese Tabellen. 

 Wählen Sie anhand der Anleitungen in diesem Abschnitt für jede Tabelle einen Verteilungsstil aus. Erstellen Sie anschließend die Tabellen, landen Sie sie mit Daten, die den realen Daten so ähnlich wie möglich sind. Testen Sie dann die Tabellen auf die Abfragetypen, die Sie verwenden möchten. Sie können die Abfragebeschreibungspläne auswerten, um Optimierungsmöglichkeiten zu identifizieren. Vergleichen Sie Ladezeiten, Speicheranforderungen und Abfragelaufzeiten, um die Anforderungen Ihres Systems insgesamt auszugleichen. 

# Bezeichnen von Verteilungsstilen
<a name="t_designating_distribution_styles"></a>

 Die Überlegungen und Empfehlungen für die Bezeichnung von Verteilungsstilen in diesem Abschnitt verwenden ein Sternschema als Beispiel. Ihr Datenbankdesign könnte auf einem Sternschema, einer Sternschemavariante oder einem ganz anderen Schema beruhen. Amazon Redshift wurde entwickelt, um effektiv mit jedem Schemadesign zu arbeiten, das Sie wählen. Die Grundsätze in diesem Abschnitt können auf jedes Schemadesign angewendet werden. 

1.  **Geben Sie die Primär- und Fremdschlüssel für alle Ihre Tabellen an.** 

   Amazon Redshift setzt keine Einschränkungen für Primär- und Fremdschlüssel durch. Der Abfrageoptimierer verwendet sie jedoch beim Generieren von Abfrageplänen. Wenn Sie Primär- und Fremdschlüssel festlegen, muss Ihre Anwendung die Gültigkeit der Schlüssel wahren. 

1.  **Verteilen Sie die Faktentabelle und ihre größte Dimensionstabelle anhand ihrer gemeinsamen Spalten.** 

   Wählen Sie die größte Dimension basierend auf der Größe des Datensatzes aus, der am häufigsten Join beteiligt ist, nicht nur basierend auf der Größe der Tabelle. Wenn eine Tabelle unter Verwendung einer WHERE-Klausel gefiltert ist, ist nur ein Teil ihrer Zeilen am Join beteiligt. Eine solche Tabelle wirkt sich weniger auf die Umverteilung aus als eine kleinere Tabelle, die mehr Daten beiträgt. Bezeichnen Sie den Primärschlüssel der Dimensionstabelle und den entsprechenden Fremdschlüssel der Faktentabelle als DISTKEY. Wenn mehrere Tabellen denselben Verteilungsschlüssel verwenden, werden sie ebenfalls zusammen mit der Faktentabelle platziert. Ihre Faktentabelle kann nur einen Verteilungsschlüssel haben. Alle Tabellen, die auf einem anderen Schlüssel verbunden werden, werden nicht mit der Faktentabelle zusammengestellt. 

1.  **Bezeichnen Sie die Verteilungsschlüssel für die anderen Dimensionstabellen.** 

   Verteilt die Tabellen anhand ihrer Primär- oder Fremdschlüssel, abhängig davon wie sie am häufigsten Joins mit anderen Tabellen ausführen. 

1.  **Überprüfen Sie, ob die Verteilung einiger Dimensionstabellen in eine ALL-Verteilung geändert werden sollte.** 

   Wenn eine Dimensionstabelle nicht mit der Faktentabelle oder anderen wichtigen Joining-Tabellen zusammengestellt werden kann, können Sie die Abfrageleistung dadurch erheblich verbessern, dass Sie die gesamte Tabelle zu allen Knoten verteilen. Die Verwendung der ALL-Verteilung vervielfacht die Speicheranforderungen, verlängert Ladezeiten und erhöht den Aufwand für Wartungsoperationen. Sie sollten daher alle Faktoren sorgfältig abwägen, bevor Sie die ALL-Verteilung wählen. Im folgenden Abschnitt wird beschrieben, wie Sie Kandidaten für die ALL-Verteilung durch Auswerten des EXPLAIN-Plans identifizieren. 

1.  **Verwenden Sie die AUTO-Verteilung für die übrigen Tabellen.** 

   Wenn eine Tabelle zum großen Teil denormalisiert ist und nicht an Joins beteiligt ist oder es keine klare Wahl für einen anderen Verteilungsstil gibt, verwenden Sie die AUTO-Verteilung. 

Wenn Sie möchten, dass Amazon Redshift einen geeigneten Verteilungsstil auswählt, geben Sie keinen Verteilungsstil an.

# Auswerten des Abfrageplans
<a name="c_data_redistribution"></a>

Sie können Abfragepläne verwenden, um Kandidaten für die Optimierung des Verteilungsstils zu identifizieren. 

Nachdem Sie Ihre anfänglichen Designentscheidungen getroffen haben, erstellen Sie Ihre Tabellen, laden Daten in sie und testen sie. Verwenden Sie einen Testdatensatz, der so nahe an den realen Daten wie möglich ist. Messen Sie die Ladezeiten, um sie als Ausgangspunkt für Vergleiche verwenden zu können. 

Werten Sie Abfragen aus, die repräsentativ für die aufwändigsten Abfragen sind, die Sie voraussichtlich ausführen werden, insbesondere Abfragen, die Joins und Aggregationen verwenden. Vergleichen Sie die Laufzeiten für verschiedene Designoptionen. Wenn Sie die Laufzeiten vergleichen, sollten Sie die erste Ausführung der Abfrage nicht berücksichtigen, da die erste Laufzeit die Kompilierungszeit enthält. 

**DS\$1DIST\$1NONE**  
Es ist keine Umverteilung erforderlich, da korrespondierende Slices auf den Datenverarbeitungsknoten zusammen platziert werden. In der Regel gibt es nur einen DS\$1DIST\$1NONE-Schritt, den Join zwischen der Faktentabelle und einer einzelnen Dimensionstabelle. 

**DS\$1DIST\$1ALL\$1NONE**  
Es ist keine Umverteilung erforderlich, da die innere Join-Tabelle bereits DISTSTYLE ALL verwendet hat. Die gesamte Tabelle befindet sich auf jedem Knoten. 

**DS\$1DIST\$1INNER**  
Die innere Tabelle wird umverteilt. 

**DS\$1DIST\$1OUTER**  
Die äußere Tabelle wird umverteilt. 

**DS\$1BCAST\$1INNER**  
Eine Kopie der gesamten inneren Tabelle wird an alle Verarbeitungsknoten gesendet. 

**DS\$1DIST\$1ALL\$1INNER**  
Die gesamte innere Tabelle wird an eine einzige Slice umverteilt wurde, weil die äußere Tabelle DISTSTYLE ALL verwendet.

**DS\$1DIST\$1BOTH**  
Beide Tabellen werden umverteilt. 

**DS\$1DIST\$1ERR**  
Wenn für die Tabelle kein Verteilungsstil ausgewählt ist.

DS\$1DIST\$1NONE und DS\$1DIST\$1ALL\$1NONE sind gut. Sie zeigen an, dass für diesen Schritt keine Verteilung erforderlich war, da alle Joins zusammen platziert waren. 

DS\$1DIST\$1INNER bedeutet, dass der Schritt wahrscheinlich relativ hohe Kosten verursacht, da die innere Tabelle an die Knoten umverteilt wird. DS\$1DIST\$1INNER zeigt an, dass die äußere Tabelle bereits korrekt anhand des Join-Schlüssels verteilt wurde. Legen Sie den Verteilungsschlüssel der inneren Tabelle auf den Join-Schlüssel fest, um dies in DS\$1DIST\$1NONE zu konvertieren. In einigen Fällen ist eine Verteilung der inneren Tabelle auf den Join-Schlüssel nicht möglich, da die äußere Tabelle nicht auf den Join-Schlüssel verteilt ist. Wenn dies der Fall ist, prüfen Sie, ob die ALL-Verteilung für die innere Tabelle verwendet werden soll. Wenn die Tabelle nicht häufig oder umfassend aktualisiert wird, und groß genug ist, um zu hohen Umverteilungskosten zu führen, ändern Sie den Verteilungsschlüssel in ALL und führen den Test erneut aus. Die ALL-Verteilung verursacht höhere Ladezeiten. Berücksichtigen Sie daher die Ladezeit bei Ihrer Auswertung, wenn Sie den Test erneut ausführen. 

DS\$1DIST\$1ALL\$1INNER ist nicht gut. Dies bedeutet, dass die gesamte innere Tabelle an einen einzelnen Slice umverteilt wird, da die äußere Tabelle DISTSTYLE ALL verwendet, sodass sich auf jedem Knoten eine Kopie der gesamten äußeren Tabelle befindet. Dies führt zu einer ineffizienten seriellen Laufzeit des Joins auf einem einzelnen Knoten, anstatt die Vorteile einer parallelen Laufzeit unter Verwendung aller Knoten zu nutzen. DISTSTYLE ALL ist nur für die Verwendung für die innere Join-Tabelle vorgesehen. Geben Sie stattdessen einen Verteilungsschlüssel an oder verwenden Sie für die äußere Tabelle die EVEN-Verteilung.

DS\$1BCAST\$1INNER und DS\$1DIST\$1BOTH sind nicht gut. In der Regel erfolgen diese Umverteilungen, da für die Tabellen kein Join anhand ihrer Verteilungsschlüssel ausgeführt wurde. Wenn die Faktentabelle noch nicht über einen Verteilungsschlüssel verfügt, geben Sie für beide Tabellen die Join-Spalte als Verteilungsschlüssel an. Wenn die Faktentabelle bereits über einen Verteilungsschlüssel anhand einer anderen Spalte verfügt, überprüfen Sie, ob eine Änderung des Verteilungsschlüssels, damit dieser Join zusammen platziert werden kann, die Leistung insgesamt verbessert. Wenn die Änderung des Verteilungsschlüssels der äußeren Tabelle keine optimale Wahl darstellt, können Sie eine gemeinsame Platzierung erzielen, indem Sie für die innere Tabelle DISTSTYLE ALL angeben. 

 Im folgenden Beispiel wird ein Teil eines Abfrageplans mit den Bezeichnungen DS\$1BCAST\$1INNER und DS\$1DIST\$1NONE gezeigt.

```
->  XN Hash Join DS_BCAST_INNER  (cost=112.50..3272334142.59 rows=170771 width=84)
        Hash Cond: ("outer".venueid = "inner".venueid)
        ->  XN Hash Join DS_BCAST_INNER  (cost=109.98..3167290276.71 rows=172456 width=47)
              Hash Cond: ("outer".eventid = "inner".eventid)
              ->  XN Merge Join DS_DIST_NONE  (cost=0.00..6286.47 rows=172456 width=30)
                    Merge Cond: ("outer".listid = "inner".listid)
                    ->  XN Seq Scan on listing  (cost=0.00..1924.97 rows=192497 width=14)
                    ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=24)
```

Nach der Änderung des Verteilungsstils der Dimensionstabellen in DISTSTYLE ALL zeigt der Abfrageplan für dieselbe Abfrage DS\$1DIST\$1ALL\$1NONE anstelle von DS\$1BCAST\$1INNER. Es gibt darüber hinaus eine wesentliche Änderung bei den relativen Kosten für die Join-Schritte. Die Gesamtkosten sind `14142.59` verglichen mit `3272334142.59` in der vorherigen Abfrage.

```
->  XN Hash Join DS_DIST_ALL_NONE  (cost=112.50..14142.59 rows=170771 width=84)
        Hash Cond: ("outer".venueid = "inner".venueid)
        ->  XN Hash Join DS_DIST_ALL_NONE  (cost=109.98..10276.71 rows=172456 width=47)
              Hash Cond: ("outer".eventid = "inner".eventid)
              ->  XN Merge Join DS_DIST_NONE  (cost=0.00..6286.47 rows=172456 width=30)
                    Merge Cond: ("outer".listid = "inner".listid)
                    ->  XN Seq Scan on listing  (cost=0.00..1924.97 rows=192497 width=14)
                    ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=24)
```

# Beispiel für einen Abfrageplan
<a name="t_explain_plan_example"></a>

In diesem Beispiel wird gezeigt, wie Sie einen Abfrageplan auswerten, um Möglichkeiten für die Optimierung der Distribution zu identifizieren.

Führen Sie die folgende Abfrage mit einem EXPLAIN-Befehl aus, um einen Abfrageplan zu generieren.

```
explain
select lastname, catname, venuename, venuecity, venuestate, eventname, 
month, sum(pricepaid) as buyercost, max(totalprice) as maxtotalprice
from category join event on category.catid = event.catid
join venue on venue.venueid = event.venueid
join sales on sales.eventid = event.eventid
join listing on sales.listid = listing.listid
join date on sales.dateid = date.dateid
join users on users.userid = sales.buyerid
group by lastname, catname, venuename, venuecity, venuestate, eventname, month
having sum(pricepaid)>9999
order by catname, buyercost desc;
```

SALES ist in der Datenbank TICKIT eine Faktentabelle und LISTING ist ihre größte Dimension. Um die Tabellen gemeinsam zu platzieren, wird SALES anhand der LISTID verteilt. Dies ist der Fremdschlüssel für LISTING. LISTING wird anhand ihres Primärschlüssels LISTID verteilt. Im folgenden Beispiel werden die CREATE TABLE-Befehle für SALES und LISTING gezeigt.

```
create table sales(
	salesid integer not null,
	listid integer not null distkey,
	sellerid integer not null,
	buyerid integer not null,
	eventid integer not null encode mostly16,
	dateid smallint not null,
	qtysold smallint not null encode mostly8,
	pricepaid decimal(8,2) encode delta32k,
	commission decimal(8,2) encode delta32k,
	saletime timestamp,
	primary key(salesid),
	foreign key(listid) references listing(listid),
	foreign key(sellerid) references users(userid),
	foreign key(buyerid) references users(userid),
	foreign key(dateid) references date(dateid))
        sortkey(listid,sellerid);

create table listing(
	listid integer not null distkey sortkey,
	sellerid integer not null,
	eventid integer not null encode mostly16,
	dateid smallint not null,
	numtickets smallint not null encode mostly8,
	priceperticket decimal(8,2) encode bytedict,
	totalprice decimal(8,2) encode mostly32,
	listtime timestamp,
	primary key(listid),
	foreign key(sellerid) references users(userid),
	foreign key(eventid) references event(eventid),
	foreign key(dateid) references date(dateid));
```

Im folgenden Abfrageplan zeigt der Zusammenführungs-Join-Schritt für den Join für SALES und LISTING DS\$1DIST\$1NONE. Dies zeigt, dass für den Schritt keine Umverteilung erforderlich ist. Weiter oben im Abfrageplan sehen Sie jedoch, dass die übrigen inneren Joins DS\$1BCAST\$1INNER zeigen. Dies zeigt an, dass die innere Tabelle als Teil der Abfrageausführung rundgesendet wird. Da nur ein Paar von Tabellen gemeinsam anhand der Schlüsselverteilung platziert werden kann, müssen fünf Tabellen erneut rundgesendet werden.

```
QUERY PLAN
XN Merge  (cost=1015345167117.54..1015345167544.46 rows=1000 width=103)
  Merge Key: category.catname, sum(sales.pricepaid)
  ->  XN Network  (cost=1015345167117.54..1015345167544.46 rows=170771 width=103)
        Send to leader
        ->  XN Sort  (cost=1015345167117.54..1015345167544.46 rows=170771 width=103)
              Sort Key: category.catname, sum(sales.pricepaid)
              ->  XN HashAggregate  (cost=15345150568.37..15345152276.08 rows=170771 width=103)
                    Filter: (sum(pricepaid) > 9999.00)
	                    ->  XN Hash Join DS_BCAST_INNER  (cost=742.08..15345146299.10 rows=170771 width=103)
	                          Hash Cond: ("outer".catid = "inner".catid)
	                          ->  XN Hash Join DS_BCAST_INNER  (cost=741.94..15342942456.61 rows=170771 width=97)
	                                Hash Cond: ("outer".dateid = "inner".dateid)
	                                ->  XN Hash Join DS_BCAST_INNER  (cost=737.38..15269938609.81 rows=170766 width=90)
	                                      Hash Cond: ("outer".buyerid = "inner".userid)
	                                      ->  XN Hash Join DS_BCAST_INNER  (cost=112.50..3272334142.59 rows=170771 width=84)
	                                            Hash Cond: ("outer".venueid = "inner".venueid)
	                                            ->  XN Hash Join DS_BCAST_INNER  (cost=109.98..3167290276.71 rows=172456 width=47)
	                                                  Hash Cond: ("outer".eventid = "inner".eventid)
	                                                  ->  XN Merge Join DS_DIST_NONE  (cost=0.00..6286.47 rows=172456 width=30)
	                                                        Merge Cond: ("outer".listid = "inner".listid)
	                                                        ->  XN Seq Scan on listing  (cost=0.00..1924.97 rows=192497 width=14)
	                                                        ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=24)
	                                                  ->  XN Hash  (cost=87.98..87.98 rows=8798 width=25)
	                                                        ->  XN Seq Scan on event  (cost=0.00..87.98 rows=8798 width=25)
	                                            ->  XN Hash  (cost=2.02..2.02 rows=202 width=41)
	                                                  ->  XN Seq Scan on venue  (cost=0.00..2.02 rows=202 width=41)
	                                      ->  XN Hash  (cost=499.90..499.90 rows=49990 width=14)
	                                            ->  XN Seq Scan on users  (cost=0.00..499.90 rows=49990 width=14)
	                                ->  XN Hash  (cost=3.65..3.65 rows=365 width=11)
	                                      ->  XN Seq Scan on date  (cost=0.00..3.65 rows=365 width=11)
	                          ->  XN Hash  (cost=0.11..0.11 rows=11 width=10)
	                                ->  XN Seq Scan on category  (cost=0.00..0.11 rows=11 width=10)
```

Eine Lösung besteht darin, die Tabellen zu ändern, sodass sie DISTSTYLE ALL aufweisen.

```
ALTER TABLE users ALTER DISTSTYLE ALL;
ALTER TABLE venue ALTER DISTSTYLE ALL;
ALTER TABLE category ALTER DISTSTYLE ALL;
ALTER TABLE date ALTER DISTSTYLE ALL;
ALTER TABLE event ALTER DISTSTYLE ALL;
```

Führen Sie denselben Abfrageplan mit EXPLAIN erneut aus und untersuchen Sie den neuen Abfrageplan. Die Joins zeigen nun DS\$1DIST\$1ALL\$1NONE. Dies zeigt an, dass keine Umverteilung erforderlich ist, da die Daten mittels DISTSTYLE ALL an alle Knoten verteilt wurden.

```
QUERY PLAN
XN Merge  (cost=1000000047117.54..1000000047544.46 rows=1000 width=103)
  Merge Key: category.catname, sum(sales.pricepaid)
  ->  XN Network  (cost=1000000047117.54..1000000047544.46 rows=170771 width=103)
        Send to leader
        ->  XN Sort  (cost=1000000047117.54..1000000047544.46 rows=170771 width=103)
              Sort Key: category.catname, sum(sales.pricepaid)
              ->  XN HashAggregate  (cost=30568.37..32276.08 rows=170771 width=103)
                    Filter: (sum(pricepaid) > 9999.00)
                    ->  XN Hash Join DS_DIST_ALL_NONE  (cost=742.08..26299.10 rows=170771 width=103)
                          Hash Cond: ("outer".buyerid = "inner".userid)
                          ->  XN Hash Join DS_DIST_ALL_NONE  (cost=117.20..21831.99 rows=170766 width=97)
                                Hash Cond: ("outer".dateid = "inner".dateid)
                                ->  XN Hash Join DS_DIST_ALL_NONE  (cost=112.64..17985.08 rows=170771 width=90)
                                      Hash Cond: ("outer".catid = "inner".catid)
                                      ->  XN Hash Join DS_DIST_ALL_NONE  (cost=112.50..14142.59 rows=170771 width=84)
                                            Hash Cond: ("outer".venueid = "inner".venueid)
                                            ->  XN Hash Join DS_DIST_ALL_NONE  (cost=109.98..10276.71 rows=172456 width=47)
                                                  Hash Cond: ("outer".eventid = "inner".eventid)
                                                  ->  XN Merge Join DS_DIST_NONE  (cost=0.00..6286.47 rows=172456 width=30)
                                                        Merge Cond: ("outer".listid = "inner".listid)
                                                        ->  XN Seq Scan on listing  (cost=0.00..1924.97 rows=192497 width=14)
                                                        ->  XN Seq Scan on sales  (cost=0.00..1724.56 rows=172456 width=24)
                                                  ->  XN Hash  (cost=87.98..87.98 rows=8798 width=25)
                                                        ->  XN Seq Scan on event  (cost=0.00..87.98 rows=8798 width=25)
                                            ->  XN Hash  (cost=2.02..2.02 rows=202 width=41)
                                                  ->  XN Seq Scan on venue  (cost=0.00..2.02 rows=202 width=41)
                                      ->  XN Hash  (cost=0.11..0.11 rows=11 width=10)
                                            ->  XN Seq Scan on category  (cost=0.00..0.11 rows=11 width=10)
                                ->  XN Hash  (cost=3.65..3.65 rows=365 width=11)
                                      ->  XN Seq Scan on date  (cost=0.00..3.65 rows=365 width=11)
                          ->  XN Hash  (cost=499.90..499.90 rows=49990 width=14)
                                ->  XN Seq Scan on users  (cost=0.00..499.90 rows=49990 width=14)
```

# Verteilungsbeispiele
<a name="c_Distribution_examples"></a>

In den folgenden Beispielen wird gezeigt, wie Daten anhand der Optionen verteilt werden, die Sie in der CREATE TABLE-Anweisung definieren.

## Beispiele für DISTKEY
<a name="c_Distribution_examples-distkey-examples"></a>

Betrachten Sie das Schema der Tabelle USERS in der Datenbank TICKIT. USERID ist als SORTKEY-Spalte und DISTKEY-Spalte definiert: 

```
select "column", type, encoding, distkey, sortkey 
from pg_table_def where tablename = 'users';
    
    column     |          type          | encoding | distkey | sortkey
---------------+------------------------+----------+---------+---------
 userid        | integer                | none     | t       |       1
 username      | character(8)           | none     | f       |       0
 firstname     | character varying(30)  | text32k  | f       |       0

...
```

USERID ist eine gute Wahl als Verteilungsspalte für diese Tabelle. Wenn Sie eine Abfrage für die Systemansicht SVV\$1DISKUSAGE ausführen, können Sie sehen, dass die Tabelle sehr gleichmäßig verteilt ist. Die Spaltennummern sind nullbasiert. Daher ist USERID Spalte 0.

```
select slice, col, num_values as rows, minvalue, maxvalue
from svv_diskusage
where name='users' and col=0 and rows>0
order by slice, col;

slice| col | rows  | minvalue | maxvalue
-----+-----+-------+----------+----------
0    | 0   | 12496 | 4        | 49987
1    | 0   | 12498 | 1        | 49988
2    | 0   | 12497 | 2        | 49989
3    | 0   | 12499 | 3        | 49990
(4 rows)
```

Die Tabelle enthält 49.990 Zeilen. Die Spalte für Zeilen (num\$1values) zeigt, dass jeder Slice ungefähr dieselbe Zahl von Zeilen enthält. Die Spalten für den Mindest- und Maximalwert (minvalue und maxvalue) zeigen den Bereich der Werte in jedem Slice. Jedes Slice umfasst fast den gesamten Wertebereich, sodass die Wahrscheinlichkeit groß ist, dass jedes Slice an der Ausführung einer Abfrage beteiligt ist, die nach einem bestimmten IDs Benutzerbereich filtert.

Dieses Beispiel zeigt eine Verteilung für ein kleines Testsystem. Die Gesamtzahl der Slices ist in der Regel sehr viel höher.

Wenn Sie häufig Joins oder Gruppierungen anhand der Spalte STATE ausführen, sollten Sie vielleicht eine Verteilung anhand der Spalte STATE wählen. Das folgende Beispiel zeigt das Erstellen einer neuen Tabelle mit denselben Daten wie die Tabelle USERS, bei der der DISTKEY jedoch auf die Spalte STATE festgelegt wird. In diesem Fall ist die Verteilung nicht so gleichmäßig. Slice 0 (13.587 Zeilen) enthält ungefähr 30 % mehr Zeilen als Slice 3 (10.150 Zeilen). In einer sehr viel größeren Tabelle könnte sich diese Verteilungsverzerrung nachteilig auf die Abfrageverarbeitung auswirken.

```
create table userskey distkey(state) as select * from users;

select slice, col, num_values as rows, minvalue, maxvalue from svv_diskusage
where name = 'userskey' and col=0 and rows>0
order by slice, col;

slice | col | rows  | minvalue | maxvalue
------+-----+-------+----------+----------
    0 |   0 | 13587 |        5 |    49989
    1 |   0 | 11245 |        2 |    49990
    2 |   0 | 15008 |        1 |    49976
    3 |   0 | 10150 |        4 |    49986
(4 rows)
```

## Beispiel für DISTSTYLE EVEN
<a name="c_Distribution_examples-diststyle-even-example"></a>

Wenn Sie eine neue Tabelle mit denselben Daten wie die Tabelle USERS erstellen, DISTSTYLE jedoch auf EVEN festlegen, werden die Zeilen stets gleichmäßig über die Slices verteilt. 

```
create table userseven diststyle even as 
select * from users;

select slice, col, num_values as rows, minvalue, maxvalue from svv_diskusage
where name = 'userseven' and col=0 and rows>0
order by slice, col;

slice | col | rows  | minvalue | maxvalue
------+-----+-------+----------+----------
    0 |   0 | 12497 |        4 |    49990
    1 |   0 | 12498 |        8 |    49984
    2 |   0 | 12498 |        2 |    49988
    3 |   0 | 12497 |        1 |    49989  
(4 rows)
```

Da die Verteilung jedoch nicht auf einer spezifischen Spalte basiert, kann die Leistung der Abfrageverarbeitung nachlassen, besonders, wenn für die Tabelle ein Join mit anderen Tabellen ausgeführt wurde. Eine fehlende Verteilung anhand einer Join-Spalte wirkt sich häufig auf den Typ der Join-Operation aus, der effizient ausgeführt werden kann. Join-, Aggregations- und Gruppierungsoperationen sind optimiert, wenn beide Tabellen anhand der jeweiligen Join-Spalten verteilt und sortiert sind.

## Beispiel für DISTSTYLE ALL
<a name="c_Distribution_examples-diststyle-all-example"></a>

Wenn Sie eine neue Tabelle mit denselben Daten wie die Tabelle USERS erstellen, DISTSTYLE jedoch auf ALL festlegen, werden alle Zeilen an den ersten Slice jedes Knotens verteilt. 

```
select slice, col, num_values as rows, minvalue, maxvalue from svv_diskusage
where name = 'usersall' and col=0 and rows > 0
order by slice, col;

slice | col | rows  | minvalue | maxvalue
------+-----+-------+----------+----------
    0 |   0 | 49990 |        4 |    49990
    2 |   0 | 49990 |        2 |    49990

(4 rows)
```