Partitioning Your Oracle Data Warehouse Just a Simple

  • Slides: 35
Download presentation
Partitioning Your Oracle Data Warehouse – Just a Simple Task? Dani Schnider Principal Consultant

Partitioning Your Oracle Data Warehouse – Just a Simple Task? Dani Schnider Principal Consultant Business Intelligence dani. schnider@trivadis. com Oracle Open World 2009, San Francisco Basel · Baden · Bern · Lausanne · Zurich · Düsseldorf · Frankfurt/M. · Freiburg i. Br. · Hamburg · Munich · Stuttgart · Vienna

About Dani Schnider § Principal Consultant at Trivadis AG, Zurich, Switzerland ú Consulting, coaching

About Dani Schnider § Principal Consultant at Trivadis AG, Zurich, Switzerland ú Consulting, coaching and development of data warehouse projects for several customers ú dani. schnider@trivadis. com § Trainer for Trivadis courses ú Data Warehousing with Oracle ú SQL Performance Tuning & Optimizer Workshop ú Oracle Warehouse Builder § Working… ú ú … with databases since 1990 … with Oracle since 1994 … with Data Warehouses since 1997 … for Trivadis since 1999 Partitioning Your Oracle Data Warehouse 2 © 2009

About Trivadis § Swiss IT consulting company ú Technical consulting with focus on Oracle,

About Trivadis § Swiss IT consulting company ú Technical consulting with focus on Oracle, SQL Server and DB/2 Hamburg ú 13 locations in Switzerland, Germany and Austria ú ~ 550 employees Düsseldorf ~170 employees § Key figures 2008 Frankfurt ú Services for more than 650 clients in over 1‘ 600 projects Stuttgart ú Over 150 Service Level Agreements Vienna Freiburg Basel Munich Brugg Baden Bern Lausanne Zurich ú More than 5'000 training participants ~10 employees ~370 employees Partitioning Your Oracle Data Warehouse 3 © 2009

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition Maintenance Data are always part of the game. Partitioning Your Oracle Data Warehouse 4 © 2009

Partitioning – The Basic Idea § Decompose tables/indexes into smaller pieces Table Partitioning Your

Partitioning – The Basic Idea § Decompose tables/indexes into smaller pieces Table Partitioning Your Oracle Data Warehouse Partitions Subpartitions 5 © 2009

Partitioning Methods in Oracle Partition Subpartition (none) RANGE HASH LIST Oracle 8 i Oracle

Partitioning Methods in Oracle Partition Subpartition (none) RANGE HASH LIST Oracle 8 i Oracle 9 i RANGE HASH Oracle 8 i LIST Oracle 9 i § Additionally: Interval Partitioning, Reference Partitioning, Virtual Column-Based Partitioning Your Oracle Data Warehouse 6 © 2009

Benefits of Partitioning § Partition Pruning ú Reduce I/O: Only relevant partitions have to

Benefits of Partitioning § Partition Pruning ú Reduce I/O: Only relevant partitions have to be accessed § Partition-Wise Joins ú Full PWJ: Join two equi-partitioned tables (parallel or serial) ú Partial PWJ: Join partitioned with non-partitioned table (parallel) § Rolling History ú Create new partitions in periodical intervals ú Drop old partitions in periodical intervals § Manageability ú Backups, statistics gathering, compressing on individual partitions Partitioning Your Oracle Data Warehouse 7 © 2009

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition Maintenance Data are always part of the game. Partitioning Your Oracle Data Warehouse 8 © 2009

Partition Methods and Partition Keys § Important questions for Partitioning: ú Which tables should

Partition Methods and Partition Keys § Important questions for Partitioning: ú Which tables should be partitioned? ú Which partition method should be used? ú Which partition key(s) should be used? § Partition key is important for ú Query optimization (partition pruning, partition-wise joins) ú ETL performance (partition exchange, rolling history) Dimension Fact Table § Typically in data warehouses ú RANGE partitioning of fact tables on DATE column ú But which DATE column? Partitioning Your Oracle Data Warehouse Dimension 9 Dimension © 2009

Practical Example 1: Airline Company § Flight bookings are stored in partitioned table §

Practical Example 1: Airline Company § Flight bookings are stored in partitioned table § RANGE partitioning per month, partition key: booking date Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Oct 09 Nov 09 Dec 09 „show bookings for flights in November 2009“ § Problem: Most of the reports are based on the flight date ú Flights can be booked 11 months ahead ú 11 partitions must be read of one particular flight date Partitioning Your Oracle Data Warehouse 10 © 2009

Practical Example 1: Airline Company § Solution: partition key flight date instead of booking

Practical Example 1: Airline Company § Solution: partition key flight date instead of booking date § Data is loaded into current and future partitions Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Oct 09 Jan 10 Feb 10 Mar 10 Apr 10 Mai 10 Jun 10 Jul 10 Aug 10 Sep 10 Oct 10 Nov 09 Dec 09 „show all bookings flights for booked flights inin. November 2009“ § Reports based on flight date read only one partition § Reports based on booking date must read 11 (small) partitions Partitioning Your Oracle Data Warehouse 11 © 2009

Practical Example 1: Airline Company § Better solution: Composite RANGE-RANGE partitioning ú RANGE partitioning

Practical Example 1: Airline Company § Better solution: Composite RANGE-RANGE partitioning ú RANGE partitioning on flight date ú RANGE subpartitioning on booking date § More flexibility for reports on flight date and/or on booking date flight date Nov 09 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Oct 09 Nov 09 Dec 09 Jan 10 Feb 10 Partitioning Your Oracle Data Warehouse 12 © 2009

Practical Example 2: International Bank § Account balance data of international customers ú Monthly

Practical Example 2: International Bank § Account balance data of international customers ú Monthly files of different locations (countries) ú Correction files replace last delivery for the same month/country § Original approach ú ú Technical load id for each combination of month/country LIST partitioning on load id Load. ID 77 Files are loaded in stage table Load. ID 78 Partition exchange with current partition monthly balance file from location Stage table ETL Partitioning Your Oracle Data Warehouse Mar 2009, Switzerland Mar 2009, Germany Load. ID 79 Mar 2009, USA Load. ID 80 Apr 2009, Switzerland Load. ID 81 Apr 2009, Germany exchange partition 13 © 2009

Practical Example 2: International Bank § Problem: partition key load id is useless for

Practical Example 2: International Bank § Problem: partition key load id is useless for queries ú Queries are based on balance date § Solution ú RANGE partitioning on balance date ú LIST subpartitions on country code ú Partition exchange with subpartitions monthly balance file from location Stage table ETL Partitioning Your Oracle Data Warehouse Jan 09 CH DE FR GB US Feb 09 CH DE FR GB US Mar 09 CH DE FR GB US Apr 09 CH DE FR GB US exchange partition 14 © 2009

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition Maintenance Data are always part of the game. Partitioning Your Oracle Data Warehouse 15 © 2009

Partitioning in Star Schema Dimension § Fact Table Dimension ú Usually „big“ (millions to

Partitioning in Star Schema Dimension § Fact Table Dimension ú Usually „big“ (millions to billions of rows) ú RANGE partitioning by DATE column Fact Table § Dimension Tables ú Usually „small“ (10 to 10000 rows) ú In most cases not partitioned Dimension § But how about large dimensions? ú e. g. customer dimension with millions of rows Partitioning Your Oracle Data Warehouse 16 © 2009

HASH Partitioning on Large Dimension § DIM_CUSTOMER § FCT_SALES ú HASH Partitioning ú Partition

HASH Partitioning on Large Dimension § DIM_CUSTOMER § FCT_SALES ú HASH Partitioning ú Partition Key: CUSTOMER_ID DIM_DATE ú Composite RANGE-HASH Partitioning ú Partition Key: SALES_DATE ú Subpartition Key: CUSTOMER_ID FCT_SALES DIM_PRODUCT Jan 09 H 1 H 2 H 3 H 4 Feb 09 H 1 H 2 H 3 H 4 Mar 09 H 1 H 2 H 3 H 4 Apr 09 H 1 H 2 H 3 H 4 DIM_CUSTOMER H 1 H 2 H 3 H 4 Partitioning Your Oracle Data Warehouse 17 DIM_CHANNEL © 2009

HASH Partitioning on Large Dimension SELECT d. cal_month, c. country_name, SUM(f. amount) FROM fct_sales

HASH Partitioning on Large Dimension SELECT d. cal_month, c. country_name, SUM(f. amount) FROM fct_sales f JOIN dim_date d ON (d. cal_date = f. sales_date) JOIN dim_customer c ON (c. customer_id = f. customer_id) WHERE d. cal_month = 'Feb-2009' AND c. country_code = 'DE' GROUP BY d. cal_month, c. country_name; DIM_DATE FCT_SALES Partition Pruning Jan 09 H 1 H 2 H 3 H 4 Feb 09 H 1 H 2 H 3 H 4 Mar 09 H 1 H 2 H 3 H 4 Apr 09 H 1 H 2 H 3 H 4 Full Partition-wise Join DIM_CUSTOMER H 1 H 2 H 3 H 4 Partitioning Your Oracle Data Warehouse 18 © 2009

Practical Example 3: Telecommunication Company hash-(sub)partitioning over BK_Account Partitioning Your Oracle Data Warehouse 19

Practical Example 3: Telecommunication Company hash-(sub)partitioning over BK_Account Partitioning Your Oracle Data Warehouse 19 © 2009

LIST Partitioning on Large Dimension § DIM_CUSTOMER ú LIST Partitioning ú Partition Key: COUNTRY_CODE

LIST Partitioning on Large Dimension § DIM_CUSTOMER ú LIST Partitioning ú Partition Key: COUNTRY_CODE DIM_DATE § FCT_SALES ú Composite RANGE-LIST Partitioning ú Partition Key: SALES_DATE ú Subpartition Key: COUNTRY_CODE (denormalized column in fact table) DIM_PRODUCT FCT_SALES Jan 09 CH DE FR GB US Feb 09 CH DE FR GB US Mar 09 CH DE FR GB US Apr 09 CH DE FR GB US DIM_CUSTOMER CH DE FR GB US Partitioning Your Oracle Data Warehouse 20 DIM_CHANNEL © 2009

LIST Partitioning on Large Dimension SELECT FROM JOIN d. cal_month, c. country_name, SUM(f. amount)

LIST Partitioning on Large Dimension SELECT FROM JOIN d. cal_month, c. country_name, SUM(f. amount) fct_sales f dim_date d ON (d. cal_date = f. sales_date) dim_customer c ON (c. customer_id = f. customer_id AND c. country_code = f. country_code) WHERE d. cal_month = 'Feb-2009' AND c. country_code = 'DE' GROUP BY d. cal_month, c. country_name; DIM_DATE FCT_SALES Jan 09 CH DE FR GB US Feb 09 CH DE FR GB US Mar 09 CH DE FR GB US Apr 09 CH DE FR GB US Full Partition-wise Join DIM_CUSTOMER CH DE FR GB Partition Pruning US Partitioning Your Oracle Data Warehouse 21 © 2009

Join-Filter Pruning § New approach for partition pruning on join conditions ú A bloom

Join-Filter Pruning § New approach for partition pruning on join conditions ú A bloom filter is created based on the dimension table restriction ú Dynamic partition pruning based on that bloom filter ---------------------------------------| Id | Operation | Name | Rows | Pstart| Pstop | ---------------------------------------| 0 | SELECT STATEMENT | | 1 | HASH GROUP BY | | 1 | |* 2 | HASH JOIN | | 1886 | |* 3 | HASH JOIN | | 1886 | | 4 | PART JOIN FILTER CREATE | : BF 0000 | 30 | |* 5 | TABLE ACCESS FULL | DIM_DATE | 30 | | 6 | PARTITION RANGE JOIN-FILTER| | 21675 |: BF 0000| | 7 | PARTITION LIST SINGLE | | 21675 | KEY | | 8 | TABLE ACCESS FULL | FCT_SALES | 21675 | KEY | | 9 | PARTITION LIST SINGLE | | 8220 | KEY | | 10 | TABLE ACCESS FULL | DIM_CUSTOMER | 8220 | 2 | ---------------------------------------- Partitioning Your Oracle Data Warehouse 22 © 2009

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition

Agenda § Partitioning Concepts § The Right Partition Key § Large Dimensions § Partition Maintenance Data are always part of the game. Partitioning Your Oracle Data Warehouse 23 © 2009

Practical Example 3: Monthly Partition Maintenance § Requirements ú ú Monthly partitions on all

Practical Example 3: Monthly Partition Maintenance § Requirements ú ú Monthly partitions on all fact tables, daily inserts into current partitions 3 years of history (36 partitions per table) Table compression to increase full table scan performance Backup of current partitions only TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Oct 06 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 24 Sep 09 © 2009

Practical Example 3: Monthly Partition Maintenance 1. Set next tablespace to read-write ALTER TABLESPACE

Practical Example 3: Monthly Partition Maintenance 1. Set next tablespace to read-write ALTER TABLESPACE ts_22 READ WRITE; TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Oct 06 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 25 Sep 09 © 2009

Practical Example 3: Monthly Partition Maintenance 1. 2. Set next tablespace to read-write Drop

Practical Example 3: Monthly Partition Maintenance 1. 2. Set next tablespace to read-write Drop oldest partition ALTER TABLE sales DROP PARTITION p_oct_2006; TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 26 Sep 09 © 2009

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. Set next tablespace to read-write

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. Set next tablespace to read-write Drop oldest partition Create new partition for next month ALTER TABLE sales ADD PARTITION p_oct_2009 VALUES LESS THAN (TO_DATE('01 -NOV-2009', 'DD-MON-YYYY')) TABLESPACE ts_22; TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Oct 09 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 27 © 2009

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. 4. Set next tablespace to

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. 4. Set next tablespace to read-write Drop oldest partition Create new partition for next month ALTER TABLE sales MOVE PARTITION p_sep_2009 COMPRESS; Compress current partition TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 28 Oct 09 © 2009

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. 4. 5. Set next tablespace

Practical Example 3: Monthly Partition Maintenance 1. 2. 3. 4. 5. Set next tablespace to read-write Drop oldest partition ALTER TABLESPACE ts_21 READ ONLY; Create new partition for next month Compress current partition Set tablespace to read-only TS_01 TS_02 TS_03 TS_04 TS_05 TS_06 TS_07 TS_08 TS_09 TS_10 TS_11 TS_12 Jan 08 Feb 08 Mar 08 Apr 08 Mai 08 Jun 08 Jul 08 Aug 08 Sep 08 Oct 08 Nov 08 Dec 08 TS_13 TS_14 TS_15 TS_16 TS_17 TS_18 TS_19 TS_20 TS_21 TS_22 TS_23 TS_24 Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Nov 06 Dec 06 TS_25 TS_26 TS_27 TS_28 TS_29 TS_30 TS_31 TS_32 TS_33 TS_34 TS_35 TS_36 Jan 07 Feb 07 Mar 07 Apr 07 Mai 07 Jun 07 Jul 07 Aug 07 Sep 07 Oct 07 Nov 07 Dec 07 Partitioning Your Oracle Data Warehouse 29 Oct 09 © 2009

Interval Partitioning § In Oracle 11 g, the creation of new partitions can be

Interval Partitioning § In Oracle 11 g, the creation of new partitions can be automated § Example: CREATE TABLE sales ( prod_id NUMBER(6) NOT NULL, cust_id NUMBER NOT NULL, time_id DATE NOT NULL, channel_id CHAR(1) NOT NULL, promo_id NUMBER(6) NOT NULL, quantity_sold NUMBER(3) NOT NULL, amount_sold NUMBER(10, 2) NOT NULL ) PARTITION BY RANGE (time_id) INTERVAL(numtoyminterval(1, 'MONTH')) STORE IN (ts_01, ts_02, ts_03, ts_04) ( PARTITION p_before_1_jan_2005 VALUES LESS THAN (to_date('01 -01 -2008', 'dd-mm-yyyy')) ) Partitioning Your Oracle Data Warehouse 30 © 2009

Gathering Optimizer Statistics § DBMS_STATS parameter GRANULARITY defines statistics level GRANULARITY Parameter Value Table

Gathering Optimizer Statistics § DBMS_STATS parameter GRANULARITY defines statistics level GRANULARITY Parameter Value Table Statistics GLOBAL AND PARTITION Partition Statistics Subpartition Statistics PARTITION SUBPARTITION ALL AUTO ( ) APPROX_GLOBAL AND PARTITION § Example: dbms_stats. gather_table_stats (ownname => USER , tabname => 'SALES' , granularity => 'GLOBAL AND PARTITION'); Partitioning Your Oracle Data Warehouse 31 © 2009

Problem of Global Statistics § Global statistics are essential for good execution plans ú

Problem of Global Statistics § Global statistics are essential for good execution plans ú num_distinct, low_value, high_value, density, histograms § Gathering global statistics is time-consuming ú All partitions must be scanned Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 Aug 09 Sep 09 Oct 09 gather statistics for current partition gather global statistics Data Dictionary § Typical approach ú After loading data, only modified partition statistics are gathered ú Global statistics are gathered on regular time base (e. g. weekends) Partitioning Your Oracle Data Warehouse 32 © 2009

Incremental Global Statistics § Synopsis-based gathering of statistics § For each partition a synopsis

Incremental Global Statistics § Synopsis-based gathering of statistics § For each partition a synopsis is stored in SYSAUX tablespace ú Statistics metadata for partition and columns of partition § Global statistics by aggregating the synopses from each partition Jan 09 Feb 09 Mar 09 Apr 09 Mai 09 Jun 09 Jul 09 § Activate incremental global statistics: dbms_stats. set_table_prefs (ownname => USER , tabname => 'SALES' , pname => 'incremental' , pvalue => 'true'); Partitioning Your Oracle Data Warehouse Aug 09 Sep 09 gather statistics for current partition gather incremental global statistics 33 Oct 09 synopsis © 2009

Partitioning Your Data Warehouse – Core Messages Knowledge transfer is only the beginning. Knowledge

Partitioning Your Data Warehouse – Core Messages Knowledge transfer is only the beginning. Knowledge application is what counts. Partitioning Your Oracle Data Warehouse § Oracle Partitioning is a powerful option – not only for data warehouses § The concept is simple, but the reality can be complex § Many new partitioning features added in Oracle Database 11 g J J New Composite Partitioning methods Interval Partitioning Join-Filter Pruning Incremental Global Statistics 34 © 2009

 Thank you! ? www. trivadis. com Baden Basel Bern Brugg Lausanne Zurich Düsseldorf

Thank you! ? www. trivadis. com Baden Basel Bern Brugg Lausanne Zurich Düsseldorf Frankfurt/M. Freiburg i. Br. Hamburg Munich Stuttgart Vienna