Analysera komplexa datatyper i Azure Synapse Analytics

Den här artikeln är relevant för Parquet-filer och -containrar i Azure Synapse Link för Azure Cosmos DB. Du kan använda Spark eller SQL för att läsa eller transformera data med komplexa scheman, till exempel matriser eller kapslade strukturer. Följande exempel kompletteras med ett enda dokument, men det kan enkelt skalas till miljarder dokument med Spark eller SQL. Koden som ingår i den här artikeln använder PySpark (Python).

Användningsfall

Komplexa datatyper blir allt vanligare och utgör en utmaning för datatekniker. Analys av kapslade scheman och matriser kan innebära tidskrävande och komplexa SQL-frågor. Dessutom kan det vara svårt att byta namn på eller omvandla datatypen kapslade kolumner. När du arbetar med djupt kapslade objekt kan du dessutom stöta på prestandaproblem.

Datatekniker måste förstå hur komplexa datatyper kan bearbetas effektivt och göra dem lättillgängliga för alla. I följande exempel använder du Spark i Azure Synapse Analytics för att läsa och transformera objekt till en plan struktur via dataramar. Du använder den serverlösa sql-modellen i Azure Synapse Analytics för att köra frågor mot sådana objekt direkt och returnera dessa resultat som en vanlig tabell.

Vad är matriser och kapslade strukturer?

Följande objekt kommer från Application Insights. I det här objektet finns kapslade strukturer och matriser som innehåller kapslade strukturer.

{
    "id": "66532691-ab20-11ea-8b1d-936b3ec64e54",
    "context": {
        "data": {
            "eventTime": "2020-06-10T13:43:34.553Z",
            "samplingRate": "100.0",
            "isSynthetic": "false"
        },
        "session": {
            "isFirst": "false",
            "id": "38619c14-7a23-4687-8268-95862c5326b1"
        },
        "custom": {
            "dimensions": [
                {
                    "customerInfo": {
                        "ProfileType": "ExpertUser",
                        "RoomName": "",
                        "CustomerName": "diamond",
                        "UserName": "XXXX@yahoo.com"
                    }
                },
                {
                    "customerInfo": {
                        "ProfileType": "Novice",
                        "RoomName": "",
                        "CustomerName": "topaz",
                        "UserName": "XXXX@outlook.com"
                    }
                }
            ]
        }
    }
}

Schemaexempel på matriser och kapslade strukturer

När du skriver ut schemat för objektets dataram (kallas df) med kommandot df.printschemavisas följande representation:

  • Gult representerar kapslade strukturer.
  • Grönt representerar en matris med två element.

Kod med gul och grön markering som visar schemats ursprung

_rid, _tsoch _etag har lagts till i systemet när dokumentet matades in i Azure Cosmos DB-transaktionsarkivet.

Föregående dataram räknas endast för 5 kolumner och 1 rad. Efter omvandlingen har den granskade dataramen 13 kolumner och 2 rader i tabellformat.

Platta ut kapslade strukturer och explodera matriser

Med Spark i Azure Synapse Analytics är det enkelt att omvandla kapslade strukturer till kolumner och matriselement till flera rader. Använd följande steg för implementering.

Flödesschema som visar steg för Spark-transformeringar

Definiera en funktion för att platta ut det kapslade schemat

Du kan använda den här funktionen utan att ändra den. Skapa en cell i en PySpark-anteckningsbok med följande funktion:

from pyspark.sql.functions import col

def flatten_df(nested_df):
    stack = [((), nested_df)]
    columns = []

    while len(stack) > 0:
        parents, df = stack.pop()

        flat_cols = [
            col(".".join(parents + (c[0],))).alias("_".join(parents + (c[0],)))
            for c in df.dtypes
            if c[1][:6] != "struct"
        ]

        nested_cols = [
            c[0]
            for c in df.dtypes
            if c[1][:6] == "struct"
        ]

        columns.extend(flat_cols)

        for nested_col in nested_cols:
            projected_df = df.select(nested_col + ".*")
            stack.append((parents + (nested_col,), projected_df))

    return nested_df.select(columns)

Använd funktionen för att platta ut det kapslade schemat

I det här steget plattar du ut det kapslade schemat för dataramen (df) till en ny dataram (df_flat):

from pyspark.sql.types import StringType, StructField, StructType
df_flat = flatten_df(df)
display(df_flat.limit(10))

Visningsfunktionen ska returnera 10 kolumner och 1 rad. Matrisen och dess kapslade element finns fortfarande kvar.

Transformera matrisen

Här omvandlar du matrisen, context_custom_dimensions, i dataramen df_flat, till en ny dataram df_flat_explode. I följande kod definierar du också vilken kolumn du vill välja:

from pyspark.sql.functions import explode
from pyspark.sql.functions import flatten
from pyspark.sql.functions import arrays_zip
df_flat_explode = df_flat.select("_rid","_ts","id","_etag",explode(df_flat.context_custom_dimensions),"context_session_isFirst","context_session_id","context_data_eventTime","context_data_samplingRate","context_data_isSynthetic")\
.select("_rid","_ts","id","_etag","col.*","context_session_isFirst","context_session_id","context_data_eventTime","context_data_samplingRate","context_data_isSynthetic")
display(df_flat_explode.limit(10))

Visningsfunktionen ska returnera 10 kolumner och 2 rader. Nästa steg är att platta ut kapslade scheman med funktionen som definierats i steg 1.

Använd funktionen för att platta ut det kapslade schemat

Slutligen använder du funktionen för att platta ut det kapslade schemat för dataramen df_flat_explodetill en ny dataram: df_flat_explode_flat

df_flat_explode_flat = flatten_df(df_flat_explode)
display(df_flat_explode_flat.limit(10))

Visningsfunktionen ska visa 13 kolumner och 2 rader.

Dataramens df_flat_explode_flat funktion printSchema returnerar följande resultat:

Kod som visar det slutliga schemat

Läs matriser och kapslade strukturer direkt

Med den serverlösa modellen för SQL kan du fråga och skapa vyer och tabeller över sådana objekt.

Beroende på hur data har lagrats bör användarna först använda följande taxonomi. Allt som visas i versaler är specifikt för ditt användningsfall:

Bulk Format
'https://ACCOUNTNAME.dfs.core.windows.net/FILESYSTEM/PATH/FINENAME.parquet' "Parquet" (ADLSg2)
N'endpoint=https://ACCOUNTNAME.documents-staging.windows-ppe.net:443/;account=ACCOUNTNAME;database=DATABASENAME;collection=COLLECTIONNAME;region=REGIONTOQUERY', SECRET='YOURSECRET' CosmosDB (Azure Synapse Link)

Ersätt varje fält på följande sätt:

  • "YOUR BULK ABOVE" är anslutningssträngen för den datakälla som du ansluter till.
  • "DIN TYP OVAN" är det format som du använder för att ansluta till källan.
select *
FROM
openrowset(
    BULK 'YOUR BULK ABOVE',
    FORMAT='YOUR TYPE ABOVE'
)
with (id varchar(50),
        contextdataeventTime varchar(50) '$.context.data.eventTime',
        contextdatasamplingRate varchar(50) '$.context.data.samplingRate',
        contextdataisSynthetic varchar(50) '$.context.data.isSynthetic',
        contextsessionisFirst varchar(50) '$.context.session.isFirst',
        contextsessionid varchar(50) '$.context.session.id',
        contextcustomdimensions varchar(max) '$.context.custom.dimensions'
) as q 
cross apply openjson (contextcustomdimensions) 
with ( ProfileType varchar(50) '$.customerInfo.ProfileType',
            RoomName varchar(50) '$.customerInfo.RoomName',
            CustomerName varchar(50) '$.customerInfo.CustomerName',
            UserName varchar(50) '$.customerInfo.UserName'
    )

Det finns två olika typer av åtgärder:

  • Den första åtgärdstypen anges i följande kodrad, som definierar kolumnen som kallas contextdataeventTime som refererar till det kapslade elementet . Context.Data.eventTime

    contextdataeventTime varchar(50) '$.context.data.eventTime'
    

    Den här raden definierar kolumnen med namnet contextdataeventTime som refererar till det kapslade elementet . Context>Data>eventTime

  • Den andra åtgärdstypen använder cross apply för att skapa nya rader för varje element under matrisen. Sedan definieras varje kapslat objekt.

    cross apply openjson (contextcustomdimensions) 
    with ( ProfileType varchar(50) '$.customerInfo.ProfileType', 
    

    Om matrisen hade 5 element med 4 kapslade strukturer returnerar den serverlösa sql-modellen 5 rader och 4 kolumner. Den serverlösa modellen för SQL kan fråga på plats, mappa matrisen i 2 rader och visa alla kapslade strukturer i kolumner.

Nästa steg