{"id":694,"date":"2018-08-17T01:58:08","date_gmt":"2018-08-16T23:58:08","guid":{"rendered":"https:\/\/sql.marcus-belz.de\/?p=694"},"modified":"2020-05-21T14:40:49","modified_gmt":"2020-05-21T12:40:49","slug":"ssis-vs-transact-sql-wie-viel-sql-darfs-denn-sein","status":"publish","type":"post","link":"https:\/\/sql.marcus-belz.de\/?p=694","title":{"rendered":"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf&#8217;s denn sein?"},"content":{"rendered":"<p><a href=\"https:\/\/sql.marcus-belz.de\/?p=795\" target=\"_blank\" rel=\"noopener noreferrer\">This Article in English&#8230;<\/a><\/p>\n<h2>Die Vorgeschichte zu diesem Artikel&#8230;<\/h2>\n<p><strong>SQL Server Integration <\/strong>Services (SSIS) ist ein \u00e4u\u00dferst m\u00e4chtiges Tool Set f\u00fcr die Entwicklung von ETL-Strecken. Es gibt viele gute Gr\u00fcnde, die f\u00fcr einen Einsatz von SSIS sprechen. Es gibt derer aber auch gen\u00fcgend, die dagegen sprechen. Beschr\u00e4nken wir uns auf den Microsoft Produkt Stack, dann kommt als Alternative f\u00fcr die Entwicklung von komplexen ETL Strecken (im Wesentlichen) nur noch Transact-SQL (T-SQL) in Frage.<\/p>\n<p>Dieser Artikel geh\u00f6rt zu einer <a href=\"https:\/\/sql.marcus-belz.de\/?p=614\">Serie von Artikeln<\/a>, die wichtige Entscheidungskriterien f\u00fcr die Wahl der richtigen Technologie(n) \u2013 SSIS und\/oder T-SQL \u2013 beleuchten.<\/p>\n<p>&#8212;<\/p>\n<p>Mit Blick auf die Verwendung einer Quellcodeverwaltung habe ich in dem Artikel <a href=\"https:\/\/sql.marcus-belz.de\/?p=623\"><em>SSIS vs. Transact-SQL \u2013 Quellcodeverwaltung<\/em><\/a> die Vorteile der Verwendung von SQL Skripten (und hier SQL Server <em>Stored Procedures<\/em>), etc. gegen\u00fcber SSIS herausgestellt. Die \u00c4nderungen in einer <em>Stored Procedure<\/em> k\u00f6nnen leicht durch Vergleich zweier Versionen in Visual Studio dargestellt werden. Ein \u00e4hnlicher Vergleich zweier Versionen eines SQL Server Integration Services (SSIS) Paketes zeigt selbst bei minimalen \u00c4nderungen bereits eine un\u00fcbersichtliche Anzahl an \u00c4nderungen in dem zugrundeliegenden Dokumententyp <strong>dtsx<\/strong>. Damit scheint es schier unm\u00f6glich die \u00c4nderung zweier Versionen zu identifizieren.<\/p>\n<p>In dem erw\u00e4hnten Artikel habe ich \u00fcber ein T-SQL Statement die Hierarchie-Ebenen der Mitarbeiter aus der Tabelle <strong>[AdventureWorksDW2017].[DimEmployee]<\/strong> abgeleitet, um anschlie\u00dfend auf der Basis der gefundenen Hierarchie-Ebenen 1 bis 5 ein Ranking der Urlaubs- und Krankheitsstunden zu ermitteln. Die Ermittlung sollte jeweils \u00fcber die <em>Windowed Function<\/em> <strong>NTILE()<\/strong> und <strong>DENSE_RANK()<\/strong> erfolgen. Die Klassifizierung der Mitarbeiter \u00fcber die NTILE-Funktion sollte 3 Klassen ergeben.<\/p>\n<p>Die Bearbeitung der Aufgabe mit T-SQL hat nur wenigen Minuten entwickelt. Common Table Expressions (CTE) unterst\u00fctzen rekursive Aufrufe und das Ranking konnte schnell \u00fcber die die <em>Windowed<\/em> <em>Function<\/em> ermittelt werden.<\/p>\n<p>Um die Verwendung von T-SQL Prozeduren\/Skripten mit Blick auf die Quellcodeverwaltung der Verwendung von SSIS Paketen gegen\u00fcberstellen zu k\u00f6nnen, wollte ich ein \u201cinhaltsgleiches\u201d SSIS Paket entwickeln. Ich habe mich der naiven Vorstellung hingegeben, dass diese Aufgabe zwar mit etwas mehr zeitlichem Aufwand zu l\u00f6sen ist, aber immerhin mit einem vertretbaren Aufwand l\u00f6sbar ist.<\/p>\n<p><strong>Weit gefehlt!<\/strong><\/p>\n<p>F\u00fcr die beiden wesentlichen Anforderungen gibt es meines Wissens keine einfache L\u00f6sung, geschweige denn Standard Tasks oder Funktionen, die in einer Expression verwendet werden k\u00f6nnten.<\/p>\n<ul>\n<li>Rekursive Ermittlung der Hierarchie-Ebenen<\/li>\n<li>Ermittlung des Rankings<\/li>\n<\/ul>\n<p>Einen einfachen L\u00f6sungsweg f\u00fcr die rekursive Ermittlung der Hierarchie-Ebenen habe ich weder in den Untiefen einschl\u00e4giger Blogs gefunden noch selbst auf die \u201cSchnelle\u201d ableiten k\u00f6nnen. Versuche, das Ranking gem\u00e4\u00df der Funktion NTILE() \u00fcber eine Expression zu ermitteln, habe ich schnell aufgegeben und diesen Teil der Aufgabe schlie\u00dflich \u00fcber Skript-Tasks gel\u00f6st. Das Ergebnis ist der trotz der Komplexit\u00e4t des entwickelten Artefakts \u2013 wie ich finde \u2013 recht \u00fcbersichtlich. Es ist aber eine statische L\u00f6sung und sie ist auf 5 Hierarchieebenen beschr\u00e4nkt.<\/p>\n<p>Zwischendurch blitzte dann immer wieder die Frage auf\u2026 warum hast Du das relevante SQL Statement nicht in die <strong>OLEDB SRC-<\/strong><strong>Datasource<\/strong> Task gepackt: <strong>Wieviel SQL darf\u2019s denn sein?<\/strong><\/p>\n<p>In diesem Artikel werden drei L\u00f6sungsans\u00e4tze mit Blick auf diese Fragestellung beschrieben und verglichen:<\/p>\n<ul>\n<li><strong>Komplexes SQL in einer <\/strong><strong><em>Stored Procedure<\/em><\/strong><strong><br \/>\n<\/strong>Ausgangspunkt ist eine <em>Stored Procedure<\/em>, die das Ergebnis eines SELECT Statement in eine Ziel-Tabelle schreibt. Die <em>Stored Procedure<\/em> wird von einer SQL Task im Control Flow eines SSIS Paketes aufgerufen. Ein Control Flow, sonst nichts.<\/li>\n<li><strong>Komplexes SQL in einer Data Source Task<br \/>\n<\/strong>Das SQL Statement kann alternativ auch in der Data Source Task eines SSIS Data Flows platziert werden, gefolgt von einer Destination Task, um die Daten in die Ziel-Tabelle zu schreiben. Die L\u00f6sung enth\u00e4lt einen Control Flow, einen Data Flow und zwei Data Flow Tasks.<\/li>\n<li><strong>Einfaches SQL in einer Data Source Task<br \/>\n<\/strong>Die extreme Alternative ohne SQL (au\u00dfer eines einfachen SELECTs in der Data Source Task) hat in der von mir entwickelten Variante eine \u201ctempor\u00e4re\u201d Tabelle zum Zwischenspeichern des Ergebnisses, einen Control Flow, 2 Data Flows und zahlreiche Data Flow-Tasks, die dar\u00fcber hinaus mit nicht ganz einfachen <em>Conditional Splits<\/em> und <em>Precedence Constraints<\/em> verkn\u00fcpft sind.<\/li>\n<\/ul>\n<p>Diese drei Alternativen werden in diesem Artikel unter den folgenden Gesichtspunkten bewertet:<\/p>\n<ul>\n<li>Dauer der Entwicklung<\/li>\n<li>Lesbarkeit<\/li>\n<li>Wartbarkeit<\/li>\n<li>Performance<\/li>\n<li>Funktionsumfang<\/li>\n<\/ul>\n<h2>Die drei L\u00f6sungsans\u00e4tze<\/h2>\n<p>Zun\u00e4chst werden die drei L\u00f6sungen vorgestellt. Alle L\u00f6sungen wurden mit <strong>Microsoft Visual Studio 2017<\/strong> und <strong>SQL Server 2017<\/strong> entwickelt.<\/p>\n<h3>Komplexes SQL in einer\u00a0Stored Procedure<\/h3>\n<p>Diese L\u00f6sung basiert auf einem komplexen SQL Statement, das die Daten in die Zieltabelle <strong>[dbo].[post00210001]<\/strong> schreibt. Basis des Statements ist die rekursive Verwendung einer CTE f\u00fcr die Berechnung der Hierarchie-Ebenen. Dem Statement vorangestellt ist eine TRUNCATE-Anweisung, um die Zieltabelle vor dem INSERT zu leeren. Der Name der Prozedur lautet <strong>[dbo].[spInsertpost0021]<\/strong>. Die Prozedur wird schlie\u00dflich in SSIS in dem Paket \u00fcber eine Execute SQL Task aufgerufen.<\/p>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-997\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png\" alt=\"\" width=\"733\" height=\"1024\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png 733w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-215x300.png 215w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-768x1072.png 768w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-1100x1536.png 1100w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png 1305w\" sizes=\"(max-width: 733px) 100vw, 733px\" \/><\/a><\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/sql.marcus-belz.de\/?attachment_id=996\" target=\"_blank\" rel=\"noopener noreferrer\">Source<\/a><\/p>\n<h3>Komplexes SQL in einer Data Source Task<\/h3>\n<p>Die zweite L\u00f6sung basiert auf einem SSIS Data Flow, der nichts anderes enth\u00e4lt als eine OLE-DB Source Task sowie eine OLE-DB Destination Task.<\/p>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210002.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-998 size-thumbnail\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210002-150x150.png\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210002-150x150.png 150w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210002.png 271w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/a><\/p>\n<p>Die OLE-DB Source Task definiert die Datenquelle als SQL Statement\u2026 eben das oben erw\u00e4hnte komplexe SQL Statement aus der Prozedur <strong>[dbo].[spInsertPost0021]<\/strong>, jedoch ohne den INSERT INTO Part des Statements.<\/p>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210003.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-999 size-medium\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210003-300x261.png\" alt=\"\" width=\"300\" height=\"261\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210003-300x261.png 300w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210003-768x669.png 768w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210003.png 824w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Es werden keine weiteren Transformationen in dem Data Flow durchgef\u00fchrt.<\/p>\n<h3>Einfaches SQL in einer Data Source Task<\/h3>\n<p>Die dritte L\u00f6sung verwendet ausschlie\u00dflich SSIS Tasks f\u00fcr die Berechnung der Hierarchie-Ebenen sowie des Rankings. Die gew\u00e4hlte L\u00f6sung beinhaltet einen Control Flow, zwei Data Flows und zwei Tabellen. Der Control Flow enth\u00e4lt 2 SQL Tasks sowie 2 Data Flow Tasks mit den folgenden Aufgaben:<\/p>\n<ul>\n<li><strong>0500 SQL Truncate Table<br \/>\n<\/strong>Diese Task l\u00f6scht die beiden tempor\u00e4ren Tabellen, die f\u00fcr die L\u00f6sung ben\u00f6tigt werden: <strong>[dbo].[post00210003]<\/strong> und <strong>[dbo].[post00210004]<\/strong>.<\/li>\n<li><strong>1000 DFT Calculate Levels<\/strong><br \/>\nDieser Data Flow berechnet zu jedem Mitarbeiter den Hierarchielevel. Die Berechnung ist nicht generisch und auf die 5 enthaltenen Hierarchielevel begrenzt.<\/li>\n<li><strong>2000 SQL Level Counts<\/strong><br \/>\nF\u00fcr die Berechnung des Rankings gem\u00e4\u00df der Windowed Function <strong>NTILE()<\/strong> ist es erforderlich, die Anzahl der Mitarbeiter je Hierarchielevel zu kennen. Diese SQL Task f\u00fchrt 5 SELECT Statements aus, um die Anzahl der Mitarbeiter je Level zu ermitteln und in hierf\u00fcr vorgesehenen Variablen zu speichern.<\/li>\n<li><strong>3000 DFT Calculate Ranking<\/strong><br \/>\nDer zweite Data Flow ermittelt schlie\u00dflich das Ranking mit Hilfe von Skript Tasks und speichert das Endergebnis in der Zieltabelle <strong>[dbo].[post00210004]<\/strong>.<\/li>\n<\/ul>\n<h4>Controlflow<\/h4>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210005.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1001 size-medium\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210005-300x216.png\" alt=\"\" width=\"300\" height=\"216\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210005-300x216.png 300w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210005.png 625w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h4>1000 DFT Calculate Levels<\/h4>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1002 size-large\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006-542x1024.png\" alt=\"\" width=\"542\" height=\"1024\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006-542x1024.png 542w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006-159x300.png 159w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006-768x1451.png 768w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006-813x1536.png 813w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210006.png 963w\" sizes=\"(max-width: 542px) 100vw, 542px\" \/><\/a><\/p>\n<p>Die Datenquelle <strong>1000 OLEDB Source<\/strong> enth\u00e4lt ein einfaches SQL Statement ohne weitere Berechnungen.<\/p>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210007.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1003 size-medium\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210007-300x261.png\" alt=\"\" width=\"300\" height=\"261\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210007-300x261.png 300w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210007-768x669.png 768w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210007.png 824w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h4>3000 DFT Caculate Ranking<\/h4>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210008.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1004 size-medium\" src=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210008-300x263.png\" alt=\"\" width=\"300\" height=\"263\" srcset=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210008-300x263.png 300w, https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210008.png 610w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Bewertung<\/h2>\n<h3>Dauer der Entwicklung<\/h3>\n<h4>Komplexes SQL in einer Stored Procedure<\/h4>\n<p>Bei der Entwicklung gab es \u2013 wie oben erw\u00e4hnt \u2013 zwei Herausforderungen: die Ermittlung der Hierarchie-Ebenen der Mitarbeiter und die Ermittlung des Rankings. T-SQL bietet f\u00fcr beide Herausforderungen Konzepte und L\u00f6sungen an, die eine einfache und schnelle L\u00f6sung erm\u00f6glichen. \u00dcber das Konzept der <a href=\"https:\/\/docs.microsoft.com\/de-de\/sql\/t-sql\/queries\/with-common-table-expression-transact-sql?view=sql-server-2017\">rekursiven Common Table Expression<\/a> k\u00f6nnen hierarchisch organisierte Daten schnell und mit wenig Aufwand abgefragt werden. Mit den Windowed Functions <a href=\"https:\/\/docs.microsoft.com\/de-de\/sql\/t-sql\/functions\/ntile-transact-sql?view=sql-server-2017\">NTILE()<\/a> und <a href=\"https:\/\/docs.microsoft.com\/de-de\/sql\/t-sql\/functions\/dense-rank-transact-sql?view=sql-server-2017\">DENSE_RANK()<\/a> ist auch die zweite Herausforderung mit nur wenigen Zeilen umgesetzt. Das SQL Statement ist in nur wenigen Minuten erstellt.<\/p>\n<h4>Komplexes SQL in einer Data Source Task<\/h4>\n<p>Die zweite L\u00f6sung verwendet das Komplexe SQL Statement als Datenquelle in einer Data Source Task. Das SSIS Paket der zweiten L\u00f6sung enth\u00e4lt lediglich zwei Data Flow Tasks: Eine Datenquelle und ein Datenziel. Es werden keine weiteren Transformationen durchgef\u00fchrt. Der wesentliche Aufwand ergibt sich aus der Erstellung des SQL Statements. Wie im vorigen Abschnitt erl\u00e4utert, ist dieses in nur wenigen Minuten erstellt. Das SSIS Paket selbst ist mit nur minimalem Aufwand ebenfalls schnell erstellt.<\/p>\n<h4>Einfaches SQL in einer Data Source Task<\/h4>\n<p>Diese L\u00f6sung wurde unter der Ma\u00dfgabe entwickelt, dass sowohl die Berechnung der Hierarchie-Ebenen sowie des Rankings mit den Board-Mitteln von SSIS umzusetzen sind. Die Datenquelle der Data Source Task wird durch ein einfaches SELECT Statement definiert. Alle weiteren Transformationen erfolgen \u00fcber SSIS Data Flow Tasks. Im Unterschied zu T-SQL gibt es hier nicht die eine ideale L\u00f6sung. Tats\u00e4chlich bin ich vor der Erstellung dieser Beispiel-L\u00f6sung dem Trugschluss aufgesessen, dass die beiden Herausforderungen \u00e4hnlich komfortabel in SSIS zu l\u00f6sen sind. Nach meinem derzeitigen Kenntnisstand ist das nicht m\u00f6glich. F\u00fcr die nicht generische Ermittlung der Hierarchie-Ebenen und die Ermittlung des Rankings wurden mehr als 40 Data Flow Tasks konfiguriert, die dar\u00fcber hinaus mit komplexen <em>Precedence-Constraints<\/em> und <em>Join\/Split-Tasks<\/em> verbunden sind. Die Entwicklung hat einige Stunden Zeit gekostet.<\/p>\n<h4>Fazit<\/h4>\n<p>In diesem Beispiel sind die Anforderungen mit T-SQL wesentlich schneller umgesetzt als mit (nur) SSIS. W\u00e4hrend in T-SQL der L\u00f6sungsweg mehr oder weniger vorgegeben ist, musste der L\u00f6sungsweg in SSIS erst einmal entworfen werden. Der Aufwand der Entwicklung des SQL Statements entsprach nur einem Bruchteil der Zeit, die f\u00fcr die SSIS L\u00f6sung aufgewendet werden musste.<\/p>\n<p>Je mehr SQL in einem SSIS Paket enthalten ist, desto schneller wird die Entwicklung sein.<\/p>\n<h3>Lesbarkeit<\/h3>\n<h4>Komplexes SQL in einer Stored Procedure<\/h4>\n<p>Das eigentliche SQL INSERT Statement der ersten L\u00f6sung erstreckt sich bei gro\u00dfz\u00fcgiger Strukturierung gerade mal \u00fcber ca. 80 Zeilen. Sofern das Statement zus\u00e4tzlich halbwegs ordentlich formatiert ist, ist der gew\u00e4hlte L\u00f6sungsweg schnell erfassbar. Das oben abgebildete Statement der ersten L\u00f6sung ist gut lesbar.<\/p>\n<h4>Komplexes SQL in einer Data Source Task<\/h4>\n<p>Die zweite L\u00f6sung verwendet in Teilen das SQL Statement aus der <em>Stored Procedure<\/em> <strong>[dbo].[spInsertPost0021]<\/strong> der ersten L\u00f6sung. W\u00e4hrend das SQL Statement an sich gut verst\u00e4ndlich ist, ist es innerhalb des Feldes <strong>SQL command text<\/strong> der Data Source Task nur schwer lesbar. Zum einen wird f\u00fcr die Darstellung des Textes eine proportionale Schriftart verwendet und zum anderen ist das Feld nichts anderes als ein Guck-Loch. Komplexe Statements sind nur sehr schwer \u00fcber diesen Dialog lesbar.<\/p>\n<h4>Einfaches SQL in einer Data Source Task<\/h4>\n<p>In dem auf SSIS basierenden dritten L\u00f6sungsansatz wurde als Datenquelle f\u00fcr die L\u00f6sung ein einfaches SQL Statement definiert. Die Komplexit\u00e4t liegt hier in den \u00fcber 40 Data Flow Tasks. W\u00e4hrend ein SQL Statement mehr oder minder von oben nach unten gelesen werden kann, sind bei der Lekt\u00fcre eines komplexen SSIS Paketes umfangreiche Aktionen erforderlich: Alle Tasks sind zu \u00f6ffnen, ihre Konfiguration muss gepr\u00fcft werden. Ein gro\u00dfer Teil der Logik ist \u00fcber die <em>Precedence Constraints<\/em> und <em>Join<\/em> <em>Tasks<\/em> abgebildet und muss erarbeitet werden. Die Erfassung der Logik dieser L\u00f6sung ist mit ungleich mehr Aufwand verbunden als die Erfassung des komplexen SQL Statements.<\/p>\n<h4>Fazit<\/h4>\n<p>T-SQL Statements sind bei strukturierter und formatierter Notation ungleich lesbarer als SSIS Pakete, die die gleiche Aufgabe erf\u00fcllen.<\/p>\n<p>Der Grad der Lesbarkeit richtet sich auch danach, wo das SQL Statement gespeichert und in welchem \u201eEditor\u201c das Statement per Default angezeigt wird. W\u00e4hrend eine Prozedur oder eine Statement in <strong>SQL Server Management Studio<\/strong> gut lesbar ist, ist es das in dem Dialog der Data Source Task nicht.<\/p>\n<h3>Wartbarkeit<\/h3>\n<h4>Lesbarkeit<\/h4>\n<p>Sofern bei Wartbarkeit auf die Lesbarkeit abgestellt wird, geht dieser Punkt ganz klar ebenfalls an T-SQL. Jene Stellen, die zu \u00e4ndern sind, aber auch solche, an denen neue Funktionen bereitgestellt werden, k\u00f6nnen in einem SQL Skript schnell identifiziert werden.<\/p>\n<h4>K\u00fcnftige Anforderungen<\/h4>\n<p>Wartbarkeit stellt prinzipiell auf k\u00fcnftige \u00c4nderungen ab. Hier gibt es durchaus Aspekte, die eine einfache Bewertung schwierig machen.<\/p>\n<p>Faktisch ist die Anzahl der Hierarchie-Ebenen in der Dimension <strong>[AdventureWorksDW2017].[DimEmployee] <\/strong>auf 5 beschr\u00e4nkt. Eine k\u00fcnftige \u00c4nderungen auf 6 Hierarchie-Ebenen bedeutet f\u00fcr die L\u00f6sung 1 (komplexes Statement) keinen zus\u00e4tzlichen Aufwand. Egal wie tief die Hierarchie strukturiert ist, T-SQL kommt damit \u2013 unter Ber\u00fccksichtigung der technischen Beschr\u00e4nkung auf 32.767 Rekursionen innerhalb einer rekursiven Common Table Expression \u2013 zu Recht.<\/p>\n<p>Anders sieht es bei Verwendung von vorwiegend SSIS aus. Eine Erweiterung um zus\u00e4tzliche Hierarchie-Ebenen bedeutet hier einen nicht unerheblichen Mehraufwand f\u00fcr die Anpassung des SSIS Paketes. Dramatisch hoch kann der Mehraufwand sein, wenn ein komplexer SSIS Data Flow irgendwo in der Mitte ge\u00e4ndert werden muss. Das kann zur Folge haben, dass jene Data Flow Tasks, die der \u00c4nderung folgen, komplett neu entwickelt werden m\u00fcssen.<\/p>\n<p>Auf der anderen Seite kann die Bewertung auch ganz anders ausfallen, wenn der Grund f\u00fcr eine k\u00fcnftige \u00c4nderung der Wechsel des Datenbank Providers ist. Bei einem Wechsel des Datenbank Managements Systems von zum Beispiel <strong>SQL Server<\/strong> nach <strong>Oracle<\/strong> ist nicht gew\u00e4hrleistet, dass der in SQL Statements verwendete Sprachumfang von der k\u00fcnftigen Plattform unterst\u00fctzt wird. Im schlechtesten Fall kann ein Statement nicht oder nur mit umfangreichem Aufwand an den Sprachumfang der neuen Umgebung angepasst werden. Eine k\u00fcnftige \u00c4nderung der Plattform bedeutet f\u00fcr die L\u00f6sung 3 \u2013 unter der Voraussetzung, dass der Datenbank-Provider von SSIS unterst\u00fctzt wird \u2013 keine Notwendigkeit einer funktionalen \u00c4nderung des SSIS Paketes.<\/p>\n<h4>Vergleich von zwei Versionen eines Artefaktes<\/h4>\n<p>Eine Voraussetzung f\u00fcr die Entwicklung wartbarer Artefakte ist die Versionierung der Artefakte in einer Quellcodeverwaltung. Der Entwickler muss zu jeder ausgelieferten und installierten Version einer Software oder einer ETL Strecke in der Lage sein, den Code im Repository zu identifizieren. Im Fehlerfall sind \u00c4nderungen am Code zur\u00fcckzuverfolgen, um Fehler identifizieren zu k\u00f6nnen. Mit welcher Version ist eine fehlerhafte Implementierung erfolgt? Was wurde von Version zu Version ge\u00e4ndert? Der Vergleich von jeweils zwei Versionen eines Artefaktes f\u00fchrt in der Regel schnell zu einer Antwort. In dem Artikel <a href=\"https:\/\/sql.marcus-belz.de\/?p=623\">SSIS vs. Transact-SQL \u2013 Quellcodeverwaltung<\/a> habe ich bereits die Aspekte der Vergleichbarkeit von T-SQL Statements und SSIS Paketen herausgearbeitet. Zwei Versionen eines SSIS Paketes sind schlicht nicht vergleichbar. SSIS Pakete sind unter diesem Gesichtspunkt nur sehr schwer wartbar.<\/p>\n<h4>Fazit<\/h4>\n<p>Die meisten Entwickler lagern einen gro\u00dfen Teil von Transformation bereits als SQL Statements in Data Source Tasks aus. Kaum eine Entwicklerin wird ein komplexes Statement, das mehrere Tabellen verjoint, \u00fcber einen SSIS Data Flow entwickeln wollen. Der Aufwand hierf\u00fcr w\u00e4re vergleichsweise exorbitant hoch und \u2013 das sei an dieser Stelle einfach so dahingestellt \u2013 die Performance grottig. Unter dem Aspekt der Wartbarkeit sollte dann allerdings die Frage zul\u00e4ssig sein, warum ein Statement innerhalb der Data Flow Source Task platziert wird?! W\u00e4re es nicht besser, das Statement in einer <em>View<\/em>, einer <em>Stored Function<\/em> oder einer <em>Stored Procedure<\/em> zu verpacken? In diesem Fall kann die <em>View<\/em>, die <em>Stored Function<\/em> oder die <em>Stored Procedure<\/em> \u00fcber ein Visual Studio Datenbank Projekt und einen <em>Schema Compare<\/em> schnell als SQL Skript in ein Visual Studio Datenbank Projekt \u00fcberf\u00fchrt werden und das Skript in ein Quellcode Verwaltungssystem eingecheckt werden.<\/p>\n<p>Bei der Bewertung der Vor und Nachteile von SQL gegen\u00fcber SSIS unter dem Gesichtspunkt der Wartbarkeit f\u00e4llt auch hier die Beurteilung eindeutig zu Gunsten von SQL aus.<\/p>\n<p>Es gibt eine kleine Ausnahme: Sofern sich k\u00fcnftige \u00c4nderungen aus \u00c4nderungen der Infrastruktur (anderer Datenbank-Provider, verteilte Umgebung, etc.) ergeben, sind Vor- und Nachteile der beiden Technologien im Detail gegeneinander abzuw\u00e4gen.<\/p>\n<h3>Performance<\/h3>\n<p>Es gibt zahlreiche Faktoren, die die Performance beeinflussen k\u00f6nnen und bei einem belastbaren Vergleich zu ber\u00fccksichtigen sind. Der Einfachheit halber ber\u00fccksichtige ich diese Faktoren <strong>nicht<\/strong>, um letztlich mit den von mir gemessenen Ausf\u00fchrungszeiten meine \u00dcberzeugung pauschal untermauern zu k\u00f6nnen: SSIS ist langsamer als T-SQL wenn ein SSIS Paket bereits einfache Transformationen enthalten, die ohne Probleme auch in einem SQL Statement umgesetzt werden k\u00f6nnen.<\/p>\n<p>Ein Beispiel hierf\u00fcr ist bereits das einfache Verjoinen von Tabellen. In SSIS muss ein Datenfluss vor der Verwendung in einer Join Task sortiert werden. Das Sortieren hat zur Folge, dass der Datenfluss nicht mehr asynchron verarbeitet werden kann. Die synchrone Datenverarbeitung eines Joins in SSIS ist ohne Zweifel langsamer als die Verarbeitung innerhalb eines SQL Statements in SQL Server.<\/p>\n<p>Die in diesem Artikel vorgestellte <strong>L\u00f6sung 3<\/strong> (nur SSIS) ist im Vergleich zu der <strong>L\u00f6sung 1<\/strong> (nur SQL) um den <strong>Faktor 2<\/strong> langsamer. Mir ist bewusst, dass dieses eine \u00e4u\u00dferst undifferenzierte Aussage ist.<\/p>\n<p>Der Vollst\u00e4ndigkeit halber sei allerdings erw\u00e4hnt, dass es auch Aufgaben gibt, die in SSIS wesentlich besser performen als ein SQL Statement.<\/p>\n<h4>Fazit<\/h4>\n<p>Pauschal kann die undifferenzierte Aussage getroffen werden, dass komplexe Transformationen, die nur mit SSIS umgesetzt sind, langsamer performen als eine reine SQL Umsetzung.<\/p>\n<h2>Funktionsumfang<\/h2>\n<p>Dieser Artikel behandelt eine Aufgabe, die unter anderem eindrucksvoll aufzeigt, wie unterschiedlich die Leistungsf\u00e4higkeit der gew\u00e4hlten Technologien ist. Was in diesem Beispiel mit einem vergleichsweise einfachen SQL Statement gel\u00f6st werden kann, erfordert mit SSIS einen eher komplexen L\u00f6sungsansatz. Das soll nun wahrlich kein grunds\u00e4tzliches Pl\u00e4doyer f\u00fcr T-SQL sein. Es gibt eine Menge Anforderungen, die mit T-SQL nicht oder nicht so einfach l\u00f6sbar sind. SSIS ist ungleich flexibler bez\u00fcglich Datenquellen, Parallelisierung, Dateioperationen und vieler anderer Aspekte.<\/p>\n<h4>Fazit<\/h4>\n<p>Sofern eine Aufgabe mit einfach T-SQL l\u00f6sbar ist, kann und sollte diese mit T-SQL bearbeitet werden. In allen anderen F\u00e4llen kommt nat\u00fcrlich SSIS zum Zuge.<\/p>\n<h2>Source Code<\/h2>\n<p>Die hier gezeigten Beispiele wurden in <strong>Visual Studio 2017<\/strong> in Verbindung mit einer <strong>SQL Server 2017<\/strong> Datenbank entwickelt. Der Source Code zu dem Beispiel kann \u00fcber den folgenden Link heruntergeladen werden:<\/p>\n<p><a href=\"https:\/\/sql.marcus-belz.de\/?attachment_id=1005\">Quellcode<\/a><\/p>\n<h2>Fazit<\/h2>\n<p>Mit Bezug zu der Dauer der Entwicklung, der Lesbarkeit und der Wartbarkeit f\u00e4llt die Wahl einfach. Je mehr SQL, desto schneller, lesbarer und wartbarer ist ein SSIS Paket. Mit Blick auf den Funktionsumfang kann nur eine differenzierte Betrachtung die richtige Antwort liefern. Die Berechnung von Rankings und Hierarchie, mag \u00fcber T-SQL leichter sein. Die Entwicklung und die Performance einer Fuzzy-Suche hingegen wird in SSIS wesentlich schneller sein. \u00c4hnlich verh\u00e4lt es sich bei der Performance allgemein. Es gibt Anwendungsbereiche, in denen SSIS um L\u00e4ngen besser performt als T-SQL. Immer dann, wenn es um asynchrone Datenverarbeitung geht \u2013 wenn also Daten schon geschrieben werden k\u00f6nnen, w\u00e4hrend die zu schreibenden Daten noch gelesen werden \u2013 ist SSIS den Vorzug zu geben. Das gleiche gilt insbesondere f\u00fcr die Parallelisierung von Datenoperationen. Bei einer synchronen Datenverarbeitung hingegen, wird die Wahl regelm\u00e4\u00dfig zu Gunsten von T-SQL ausfallen.<\/p>\n<p>Trotz seiner L\u00e4nge beantwortet dieser Artikel die Frage nach <strong>Wie viel SQL darf es denn sein?<\/strong> nur oberfl\u00e4chlich und in Teilen sehr undifferenziert. Mit diesem Artikel m\u00f6chte ich keine absolute Meinung pr\u00e4sentieren. Der Artikel soll eher als Anregung dienen, den Umfang der Verwendung von SSIS immer kritisch zu hinterfragen.<\/p>\n<p>Die eigentliche Frage sollte daher lauten: <strong>Wieviel SSIS soll es denn sein?<\/strong><\/p>\n<p>Als weiterf\u00fchrende Lekt\u00fcre kann ich nur den lesenswerten Artikel <a href=\"https:\/\/www.itprotoday.com\/software-development\/hidden-costs-ssis-how-avoid-sql-server-integration-services-gotchas\"><em>The Hidden Costs of SSIS: How to Avoid SQL Server Integration Services Gotchas<\/em><\/a> von <em>Michael K. Campbell<\/em> empfehlen, der die Pros und Cons bei der Wahl der besseren Technologie recht plakativ beschreibt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This Article in English&#8230; Die Vorgeschichte zu diesem Artikel&#8230; SQL Server Integration Services (SSIS) ist ein \u00e4u\u00dferst m\u00e4chtiges Tool Set f\u00fcr die Entwicklung von ETL-Strecken. Es gibt viele gute Gr\u00fcnde, die f\u00fcr einen Einsatz von SSIS sprechen. Es gibt derer <a href=\"https:\/\/sql.marcus-belz.de\/?p=694\" class=\"read-more\">Read More &#8230;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,5],"tags":[17,15,19,10,18],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf&#039;s denn sein? - Just another SQL blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/sql.marcus-belz.de\/?p=694\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf&#039;s denn sein? - Just another SQL blog\" \/>\n<meta property=\"og:description\" content=\"This Article in English&#8230; Die Vorgeschichte zu diesem Artikel&#8230; SQL Server Integration Services (SSIS) ist ein \u00e4u\u00dferst m\u00e4chtiges Tool Set f\u00fcr die Entwicklung von ETL-Strecken. Es gibt viele gute Gr\u00fcnde, die f\u00fcr einen Einsatz von SSIS sprechen. Es gibt derer Read More ...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/sql.marcus-belz.de\/?p=694\" \/>\n<meta property=\"og:site_name\" content=\"Just another SQL blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-16T23:58:08+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-05-21T12:40:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png\" \/>\n<meta name=\"author\" content=\"marcus\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"marcus\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694\",\"url\":\"https:\/\/sql.marcus-belz.de\/?p=694\",\"name\":\"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf's denn sein? - Just another SQL blog\",\"isPartOf\":{\"@id\":\"https:\/\/sql.marcus-belz.de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage\"},\"image\":{\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage\"},\"thumbnailUrl\":\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png\",\"datePublished\":\"2018-08-16T23:58:08+00:00\",\"dateModified\":\"2020-05-21T12:40:49+00:00\",\"author\":{\"@id\":\"https:\/\/sql.marcus-belz.de\/#\/schema\/person\/7b46a383907dc48ca44fae32ceb24744\"},\"breadcrumb\":{\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/sql.marcus-belz.de\/?p=694\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage\",\"url\":\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png\",\"contentUrl\":\"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png\",\"width\":1305,\"height\":1822},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/sql.marcus-belz.de\/?p=694#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/sql.marcus-belz.de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf&#8217;s denn sein?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/sql.marcus-belz.de\/#website\",\"url\":\"https:\/\/sql.marcus-belz.de\/\",\"name\":\"Just another SQL blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/sql.marcus-belz.de\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/sql.marcus-belz.de\/#\/schema\/person\/7b46a383907dc48ca44fae32ceb24744\",\"name\":\"marcus\",\"url\":\"https:\/\/sql.marcus-belz.de\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf's denn sein? - Just another SQL blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/sql.marcus-belz.de\/?p=694","og_locale":"en_US","og_type":"article","og_title":"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf's denn sein? - Just another SQL blog","og_description":"This Article in English&#8230; Die Vorgeschichte zu diesem Artikel&#8230; SQL Server Integration Services (SSIS) ist ein \u00e4u\u00dferst m\u00e4chtiges Tool Set f\u00fcr die Entwicklung von ETL-Strecken. Es gibt viele gute Gr\u00fcnde, die f\u00fcr einen Einsatz von SSIS sprechen. Es gibt derer Read More ...","og_url":"https:\/\/sql.marcus-belz.de\/?p=694","og_site_name":"Just another SQL blog","article_published_time":"2018-08-16T23:58:08+00:00","article_modified_time":"2020-05-21T12:40:49+00:00","og_image":[{"url":"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png"}],"author":"marcus","twitter_card":"summary_large_image","twitter_misc":{"Written by":"marcus","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/sql.marcus-belz.de\/?p=694","url":"https:\/\/sql.marcus-belz.de\/?p=694","name":"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf's denn sein? - Just another SQL blog","isPartOf":{"@id":"https:\/\/sql.marcus-belz.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage"},"image":{"@id":"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage"},"thumbnailUrl":"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001-733x1024.png","datePublished":"2018-08-16T23:58:08+00:00","dateModified":"2020-05-21T12:40:49+00:00","author":{"@id":"https:\/\/sql.marcus-belz.de\/#\/schema\/person\/7b46a383907dc48ca44fae32ceb24744"},"breadcrumb":{"@id":"https:\/\/sql.marcus-belz.de\/?p=694#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/sql.marcus-belz.de\/?p=694"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/sql.marcus-belz.de\/?p=694#primaryimage","url":"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png","contentUrl":"https:\/\/sql.marcus-belz.de\/wp-content\/uploads\/2020\/05\/post00210001.png","width":1305,"height":1822},{"@type":"BreadcrumbList","@id":"https:\/\/sql.marcus-belz.de\/?p=694#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/sql.marcus-belz.de\/"},{"@type":"ListItem","position":2,"name":"SSIS vs. SQL \u2013 Lesbarkeit\/Wartbarkeit -oder- Wie viel SQL darf&#8217;s denn sein?"}]},{"@type":"WebSite","@id":"https:\/\/sql.marcus-belz.de\/#website","url":"https:\/\/sql.marcus-belz.de\/","name":"Just another SQL blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/sql.marcus-belz.de\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/sql.marcus-belz.de\/#\/schema\/person\/7b46a383907dc48ca44fae32ceb24744","name":"marcus","url":"https:\/\/sql.marcus-belz.de\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/posts\/694"}],"collection":[{"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=694"}],"version-history":[{"count":11,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/posts\/694\/revisions"}],"predecessor-version":[{"id":1032,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=\/wp\/v2\/posts\/694\/revisions\/1032"}],"wp:attachment":[{"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=694"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=694"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sql.marcus-belz.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=694"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}