Skip to main content

Skillnader mellan målplattformar

PDQ genererar SQL för sex målplattformar utifrån en och samma modell. Modellen ändras inte när målet gör det — samma objekt, attribut, relationer, affärsnycklar och klassificeringar ger samma lagerform överallt.

Det som ändras är dialekten under, och dialekter är inte lika kapabla. Vissa motorer upprätthåller en främmande nyckel; vissa registrerar den och ignorerar den; en kan inte uttrycka den alls. Vissa tar emot en kolumnbeskrivning inuti CREATE TABLE; vissa behöver en efterföljande sats; vissa har ingenstans att lägga den. De skillnaderna är inte defekter att kringgå senare — de är egenskaper hos den motor du valt, och de avgör vilka garantier du får från databasen och vilka du måste skaffa någon annanstans.

Den här sidan redovisar dem rakt av, per plattform, så att valet görs före den första genereringskörningen i stället för att upptäckas efter några hundra tabeller.

Stödda mål

SQL-generatorn genererar för Snowflake, Databricks, SQL Server, Azure Synapse, Microsoft Fabric och PostgreSQL. Allt nedan beskriver dessa sex.


Översikt​

SnowflakeDatabricksSQL ServerSynapseFabricPostgreSQL
Läser källfiler viaNamngiven STAGEread_files()OPENROWSET(BULK …)OPENROWSET(BULK …)OPENROWSET(BULK …)pg_lake-främmandetabell
Unikt villkorDeklarerat, NOT ENFORCEDGenereras inteUpprätthållsDeklarerat, NOT ENFORCEDUpprätthållsUpprätthålls
Främmande nyckelDeklarerad, NOT ENFORCEDGenereras inteDeklarerad, NOCHECKGenereras inteDeklarerad, NOT ENFORCEDUpprätthålls
KolumnkommentarerInline i CREATE TABLEInline i CREATE TABLEExtended properties——Endast base-lagret
KategorietiketterNativ kolumn-TAGUnity Catalog SET TAGSExtended propertyExtended propertyExtended propertySidotabell _column_tags
Maskering av sensitiveMaskeringspolicy— (endast etikett)Dynamic data maskingDynamic data maskingDynamic data maskingSECURITY LABEL (postgres_anon)
Iceberg-publiceringNativDelta UniForm———Faller tillbaka på vanlig tabell
Schemaläggning i databasenCREATE TASK—————
BeräkningswarehouseUSE WAREHOUSE—————
SurrogatnycklarSEQUENCEGENERATED ALWAYS AS IDENTITYIDENTITYIDENTITYIDENTITYIDENTITY

Resten av sidan förklarar vad varje rad kostar dig.


Villkor — vad som faktiskt upprätthålls​

Det här är den skillnad som betyder mest, och den som lättast missförstås. Ett villkor som syns i genererad DDL är inte samma sak som ett villkor motorn upprätthåller vid skrivning.

MålUnikt på coreFrämmande nyckelVad databasen faktiskt garanterar
PostgreSQLUNIQUE, upprätthållsFOREIGN KEY, upprätthållsBåda. En dubblerad affärsnyckel eller ett föräldralöst barn avvisas vid laddning.
SQL ServerUNIQUE NONCLUSTERED, upprätthållsLäggs till WITH NOCHECK och inaktiveras sedanEndast unikhet. Den främmande nyckeln är dokumentation som optimeraren kanske inte litar på.
FabricUNIQUE NONCLUSTERED, upprätthållsNOT ENFORCEDEndast unikhet.
SnowflakeUNIQUE … NOT ENFORCEDFOREIGN KEY … NOT ENFORCEDIngendera. Båda är metadata, för verktyg och optimerare.
SynapseUNIQUE … NOT ENFORCEDIngen sats genereras — dedikerade SQL-pooler stödjer inte främmande nycklarIngendera.
DatabricksIngen sats genererasIngen sats genererasIngendera. Delta har inget UNIQUE, och PK/FK är endast informativa.
Unikhet kommer från laddningsmönstret, inte från villkoret

På Snowflake, Databricks och Synapse hindrar databasen inte en dubblerad affärsnyckel — men ingenting skapar någon. Deduplicering på den deklarerade affärsnyckeln ingår i core-modellens genererade laddningsmönster, så core innehåller en post per affärsnyckel på varje mål, oavsett vad villkoret säger. Ett icke upprätthållet UNIQUE är metadata för optimeraren och verktygen, inte en lucka att täcka.

Det ett upprätthållet villkor dessutom skulle fånga är en skrivning som går förbi den genererade laddningen — en manuell INSERT, ett backfill-skript, ett annat verktyg som skriver rakt in i core. PostgreSQL, SQL Server och Fabric avvisar sådana; de övriga målen accepterar dem, och en QPI-kvalitetskontroll är hur du skulle upptäcka det.

Alla tre villkorsfamiljer är på som standard och styrs av ENABLE_CORE_UNIQUE, ENABLE_FOREIGN_KEY och ENABLE_PUBL_PRIMARY_KEY. Att stänga av dem är ett sätt att behålla utdata från före 3.2; det är inte ett sätt att göra ett icke upprätthållet villkor upprätthållet.


Beskrivningar och kommentarer​

En beskrivning som deklareras en gång på ett källfilsfält eller ett modellattribut hamnar olika beroende på vad motorn har att ta emot den med.

MålVar beskrivningen hamnarKonsekvens
SnowflakeCOMMENT inline i CREATE TABLE, plus ALTER … COMMENT vid ändringDokumenterad från det ögonblick tabellen finns
DatabricksCOMMENT inline i CREATE TABLE, plus ALTER … COMMENT vid ändringDetsamma, och synlig i Unity Catalog
SQL Serversp_addextendedproperty (MS_Description), efter skapandetFinns, men i extended properties snarare än i tabelldefinitionen
Synapse / FabricGenereras inteBeskrivningar lever i AME och konsolen, inte i lagret
PostgreSQLCOMMENT ON i base-lagret; core- och publiceringstabeller får ingen genererad kommentarDelvis

Bara Snowflake och Databricks dokumenterar en tabell vid födseln — kommentaren ingår i CREATE, så det finns inget fönster där tabellen existerar odokumenterad. Överallt annars appliceras beskrivningen i efterhand eller bärs inte in i databasen alls, och konsolens genererade dokumentation är den auktoritativa ytan.

Apostrofer i beskrivningar escapas på varje väg. Inline-kommentarer gör det viktigare än förr: en oescapad apostrof skulle bryta hela CREATE TABLE snarare än en avslutande ALTER.


Klassificering och maskering​

Kategorietiketter kommer från fieldDomain; känslighet kommer från flaggan sensitive. Båda genereras med den facilitet plattformen faktiskt läser.

MålKategorietikettsensitive ger
SnowflakeMODIFY COLUMN … SET TAGEn maskeringspolicy applicerad på kolumnen
DatabricksALTER COLUMN … SET TAGS i Unity CatalogEndast en klassificeringsetikett — ingen mask
SQL Server / Synapse / Fabricsp_addextendedproperty, en namngiven property per kolumnADD MASKED WITH (FUNCTION = 'default()') — dynamic data masking
PostgreSQLEn rad i den schemaegna sidotabellen _column_tagsSECURITY LABEL FOR anon … 'MASKED WITH VALUE NULL'

Tre saker följer av tabellen:

  • Databricks flaggar känsliga kolumner; det maskerar dem inte. Etiketten är vad Unity Catalog läser och vad styrningsverktyg kan agera på, men värdet är fortfarande läsbart. Om maskering är ett krav måste den komma från en Unity Catalog-policy du äger, inte från den genererade DDL:en.
  • Snowflake förutsätter att maskeringspolicyn finns. Den genererade satsen kopplar på default_masking_policy; den skapar den inte. Skapa och tilldela policyn före första körningen, annars misslyckas känslighetssatserna.
  • PostgreSQL-maskering kräver ett tillägg. SECURITY LABEL FOR anon kräver CREATE EXTENSION anon; och dess label provider. Utan det parsar satserna men misslyckas vid exekvering.

PostgreSQL håller kategorier i en sidotabell av ett strukturellt skäl: en Postgres-kolumn har exakt en kommentar, så etiketter lagrade som kommentarer skulle skriva över varandra och över beskrivningen. Sidotabellen håller en rad per etikett, vilket bevarar flera etiketter per kolumn och låter en enskild kategori tas bort utan att röra resten.

Etikettnamn är i praktiken en enkelriktad dörr

TAG_NAME, SENSITIVE_TAG_NAME och SENSITIVE_TAG_VALUE har standardvärden som är lätta att acceptera av misstag. Sätt dem till din katalogs schema före den första genereringskörningen — att döpa om en etikett över några hundra tabeller efteråt är en migrering, inte en inställningsändring.


Datatyper​

Samma deklarerade dataType löses upp till olika fysisk typ per mål. Skillnaderna är små, och tre av dem ändrar beteende.

DeklareratSnowflakeDatabricksSQL ServerSynapseFabricPostgreSQL
TextSTRINGSTRINGNVARCHAR(255)NVARCHAR(500)VARCHAR(500)VARCHAR(255)
HeltalINTEGERINTEGERDECIMAL(18,0)DECIMAL(18,0)BIGINTNUMERIC(18,0)
DecimalDECIMAL(28,8)DECIMAL(28,8)DECIMAL(28,8)DECIMAL(28,8)DECIMAL(28,8)NUMERIC(28,8)
TidsstämpelTIMESTAMPTIMESTAMPDATETIME2DATETIME2DATETIME2(3)TIMESTAMP
TidTIMESTRINGTIMETIMETIMETIME
BooleskBOOLEANBOOLEANBITBITBITBOOLEAN
SurrogatnyckelNUMBER(38,0)BIGINTBIGINTBIGINTBIGINTBIGINT
  • Databricks har ingen TIME-typ. Ett fält med enbart tid kommer in som STRING. Sortering fungerar fortfarande lexikalt för nollutfyllda värden, men aritmetik gör det inte — modellera det som en tidsstämpel om du behöver räkna med det.
  • Textlängder är begränsade på de relationella målen och obegränsade på de kolumnära. Ett värde som ryms bekvämt i Snowflakes STRING kan trunkeras eller avvisas vid 255 tecken på SQL Server och PostgreSQL, och vid 500 på Synapse och Fabric. Kontrollera det längsta förväntade värdet för fritextfält innan du väljer en relationell motor.
  • Typkonvertering är strikt på PostgreSQL. Postgres saknar TRY_CAST, så base-vyernas och core-attributens konverteringar använder rak CAST och ett felformat värde ger fel vid laddning i stället för att bli NULL. På varje annat mål degraderar ett felaktigt värde tyst; på Postgres stoppar det laddningen. Profilering före den första core-laddningen är värd mer här än någon annanstans.

Hur källfiler läses​

Varje motor når objektlagring på sitt eget sätt, och varje sätt har en förutsättning som måste finnas innan den genererade SQL:en körs. Generatorn skapar dem inte.

MålMekanismMåste finnas i förväg
SnowflakeCOPY INTO … FROM @<stage>/pathSTORAGE INTEGRATION, STAGE, FILE FORMAT, WAREHOUSE; en EXTERNAL VOLUME för Iceberg-publicering
Databricksread_files() mot en abfss://-URL eller en Unity Catalog-volymSTORAGE CREDENTIAL + EXTERNAL LOCATION med READ FILES tilldelat; ett SQL Warehouse eller DBR 13.3 LTS och senare
SQL Server / Synapse / FabricOPENROWSET(BULK …) med en formatfilMASTER KEY, DATABASE SCOPED CREDENTIAL, EXTERNAL DATA SOURCE och formatfilen utrullad
PostgreSQLEn persistent pg_lake-främmandetabell per Published-tabellPostgreSQL 15 eller senare, CREATE EXTENSION pg_lake CASCADE, molnbehörigheter konfigurerade för pg_lake, CREATE på Published-schemat

Snowflake är det enda målet där behörigheter och bas-URL lever inuti databasen, i STAGE-objektet — ett databasobjekt hos Snowflake, som heter så oavsett vad PDQ kallar sina egna lager. Överallt annars bär den genererade SQL:en lagrings-URL:en och motorn löser åtkomsten separat.

Två beteenden är värda att känna till:

  • Synapse Published-laddningar tillämpar inget filnamnsfilter. Varje annat mål avgränsar laddningen till den fil som bearbetas; på Synapse läser en Published-laddning in hela den upplösta sökvägen. Dimensionera sökvägen därefter och räkna med omläsningar.
  • PostgreSQL läser radbrytningsseparerad JSON via en främmandetabell som skapas en gång, i Published-definitionen. Dess sökväg låses vid första skapandet, och publiceraren förutsätter att den definitionen skapat den — rulla därför ut Published-definitionen före publicering.

Orkestrering​

MålSchemaläggning inuti databasenBeräkningsvalSatsstil
SnowflakeCREATE TASK, när generatorn körs för tasksUSE WAREHOUSE-prologProcedurell — EXECUTE IMMEDIATE … BEGIN … END
DatabricksIngen — använd Workflows och Jobs—Sekventiella ;-separerade satser
SQL Server / Synapse / FabricIngen — använd egen schemaläggare—Batchar separerade med GO;, DDL skyddad av IF NOT EXISTS
PostgreSQLIngen — använd egen schemaläggare—Sekventiella ;-separerade satser

Snowflake är det enda målet som kan schemalägga sig självt. På varje annan plattform är det genererade skriptet en rak följd av satser, och något utanför databasen måste köra det — Databricks Workflows, Data Factory, Airflow eller DataOps-schemaläggaren.

Körtidsstämpeln följer samma uppdelning: en sessionsvariabel på Snowflake, en bindvariabel i T-SQL-familjen och en inline citerad literal på Databricks och PostgreSQL, som saknar procedurell variabel att binda mot.


Publiceringsformat​

Publiceringsformaten som beskrivs på sidan DLS-lagret löses inte upp likadant överallt.

MålTABLEICEBERG
SnowflakeStandardtabellNativ CREATE ICEBERG TABLE, kräver en EXTERNAL VOLUME
DatabricksDelta-tabellExtern Delta-tabell med UniForm — Iceberg-metadata genereras parallellt och kan läsas av Snowflake, Trino med flera
PostgreSQLStandardtabellFaller tillbaka på en standardtabell
SQL Server / Synapse / FabricStandardtabellStöds inte — behåll formatet TABLE

Om flermotorsåtkomst till publicerade data är ett krav är Snowflake och Databricks de två mål som levererar det.


Anteckningar per plattform​

Snowflake​

Referensimplementationen, och den mest kompletta. Allt generatorn kan generera, genererar den här: inline-kommentarer, nativa etiketter, maskeringspolicyer, Iceberg, tasks, sekvenser. Avvägningen är uppsättningen — STAGE, integration, filformat, warehouse och, för Iceberg, den externa volymen måste alla finnas och vara tilldelade före första körningen.

Databricks​

Den starkaste katalogberättelsen och den svagaste villkorsberättelsen. Etiketter hamnar där Unity Catalog läser dem och kommentarer är inline, men ingenting upprätthålls: inget UNIQUE, inga fungerande primär- eller främmande nycklar, ingen mask på känsliga kolumner. Kvalitetskontroller är det enda sätt en överträdelse här över huvud taget blir synlig, så behandla dem som obligatoriska snarare än valfria — med i beräkningen att de rapporterar i efterhand snarare än förebygger. Två operativa detaljer: att ta bort en etikett går inte att köra om, eftersom Databricks ger fel om etiketten redan saknas; och DROP COLUMN kräver namnbaserad kolumnmappning i Delta, vilket generatorn aktiverar före borttagningen.

SQL Server​

Det relationella referensmålet, och det som upprätthåller mest samtidigt som det bär minst metadata: unikhet är verklig, beskrivningar går till extended properties, främmande nycklar registreras men är inaktiverade. Published-tabellen trunkeras aldrig vid omladdning — ta höjd för det i gallring och i eventuell radantalsavstämning.

Azure Synapse​

SQL Servers struktur med dedikerade poolers begränsningar ovanpå: inga främmande nycklar alls, NOT ENFORCED unika villkor, inga korsdatabasfrågor, inga beskrivningar i lagret och inget filnamnsfilter på Published-laddningar. Distributions- och indexval genereras inte — granska DDL:en och lägg till dem före produktionsbruk. Djupt nästlad JSON kan dessutom slå i OPENROWSET-radlängdsgränsen; se FAQ för lösningen.

Microsoft Fabric​

T-SQL-familjen, där Fabric Warehouse-ytan är en rörlig delmängd av SQL Server. Unikhet upprätthålls, främmande nycklar är NOT ENFORCED, beskrivningar bärs inte in. Published-källans URL viker in trusted zone-segmentet i sökvägen, så trusted zone-inställningen måste stämma med din OneLake- eller container-layout. Eftersom Fabrics T-SQL-yta förändras bör genererad DDL granskas mot den aktuella ytan före en första produktionskörning.

PostgreSQL​

Det enda målet som upprätthåller både unikhet och referentiell integritet, vilket gör det till den striktaste platsen att köra en modell på — och den där ett modelleringsfel visar sig som en misslyckad laddning i stället för som felaktiga data. Två ytterligare konsekvenser av den strikthet: identifierare genereras utan citattecken och viks till gemener, så ett modellobjekt uppkallat efter ett reserverat ord (Order, User) kommer att misslyckas; och typkonverteringar är strikta, så felformade värden ger fel i stället för NULL.


Att välja mål​

Om detta väger tyngstVälj
Referentiell integritet garanterad av databasenPostgreSQL
Styrningsmetadata som din katalog kan läsaSnowflake eller Databricks
Dokumentation buren in i själva lagretSnowflake eller Databricks
Flermotorsåtkomst till publicerade dataSnowflake, med nativ Iceberg, eller Databricks, med UniForm
Schemaläggning utan ytterligare orkestrerareSnowflake
En befintlig Microsoft-miljöSQL Server, eller Fabric för den nyare ytan

Oavsett mål är luckorna kända i förväg, och var och en har ett planerat svar: kvalitetskontroller där villkor inte upprätthålls, konsoldokumentation där kommentarer inte bärs in, katalogpolicy där maskering inte genereras. Poängen med den här sidan är att svaret planeras snarare än improviseras.

Var dock exakt med vad en QPI-kontroll gör. En QPI-kontroll rapporterar. Den blockerar inte laddningen och hindrar inte felaktig data från att nå konsumenter — den gör avvikelsen synlig. Där ett mål inte upprätthåller ett villkor kan en dubblerad affärsnyckel skrivas, och en QPI-kontroll är hur du får veta det, inte hur du förhindrar det.


Nästa steg​