U-SQL programlama kılavuzuna genel bakış

Önemli

Azure Data Lake Analytics 29 Şubat 2024'te kullanımdan kaldırıldı. Bu duyuru ile daha fazla bilgi edinin.

Veri analizi için kuruluşunuz Azure Synapse Analytics veya Microsoft Fabric kullanabilir.

U-SQL, büyük veri türü iş yükleri için tasarlanmış bir sorgu dilidir. U-SQL'in benzersiz özelliklerinden biri, SQL benzeri bildirim temelli dilin C# tarafından sağlanan genişletilebilirlik ve programlanabilirlik ile birleşimidir. Bu kılavuzda, C# tarafından etkinleştirilen U-SQL dilinin genişletilebilirliğine ve programlanabilirliğine odaklanacağız.

Gereksinimler

Visual Studio için Azure Data Lake Araçları indirip yükleyin.

U-SQL kullanmaya başlama

Aşağıdaki U-SQL betiğine bakın:

@a  =
  SELECT * FROM
    (VALUES
       ("Contoso",   1500.0, "2017-03-39"),
       ("Woodgrove", 2700.0, "2017-04-10")
    ) AS D( customer, amount, date );

@results =
  SELECT
    customer,
    amount,
    date
  FROM @a;

Bu betik iki RowSet tanımlar: @a ve @results. RowSet @results dosyasından @atanımlanır.

U-SQL betiğindeki C# türleri ve ifadeleri

U-SQL İfadesi, , ORve NOTgibi ANDU-SQL mantıksal işlemleriyle birleştirilmiş bir C# ifadesidir. U-SQL İfadeleri SELECT, EXTRACT, WHERE, HAVING, GROUP BY ve DECLARE ile kullanılabilir. Örneğin, aşağıdaki betik bir dizeyi DateTime değeri olarak ayrıştırır.

@results =
  SELECT
    customer,
    amount,
    DateTime.Parse(date) AS date
  FROM @a;

Aşağıdaki kod parçacığı, bir dizeyi DECLARE deyiminde DateTime değeri olarak ayrıştırır.

DECLARE @d = DateTime.Parse("2016/01/01");

Veri türü dönüştürmeleri için C# ifadelerini kullanma

Aşağıdaki örnekte, C# ifadelerini kullanarak tarih saat veri dönüştürme işlemini nasıl yapabileceğiniz gösterilmektedir. Bu özel senaryoda, datetime verileri dizesi gece yarısı 00:00:00 saat gösterimiyle standart tarih saatine dönüştürülür.

DECLARE @dt = "2016-07-06 10:23:15";

@rs1 =
  SELECT
    Convert.ToDateTime(Convert.ToDateTime(@dt).ToString("yyyy-MM-dd")) AS dt,
    dt AS olddt
  FROM @rs0;

OUTPUT @rs1
  TO @output_file
  USING Outputters.Text();

Bugünün tarihi için C# ifadelerini kullanma

Bugünün tarihini çekmek için aşağıdaki C# ifadesini kullanabiliriz: DateTime.Now.ToString("M/d/yyyy")

Aşağıda bu ifadenin betikte nasıl kullanılacağına yönelik bir örnek verilmişti:

@rs1 =
  SELECT
    MAX(guid) AS start_id,
    MIN(dt) AS start_time,
    MIN(Convert.ToDateTime(Convert.ToDateTime(dt<@default_dt?@default_dt:dt).ToString("yyyy-MM-dd"))) AS start_zero_time,
    MIN(USQL_Programmability.CustomFunctions.GetFiscalPeriod(dt)) AS start_fiscalperiod,
    DateTime.Now.ToString("M/d/yyyy") AS Nowdate,
    user,
    des
  FROM @rs0
  GROUP BY user, des;

.NET derlemelerini kullanma

U-SQL'in genişletilebilirlik modeli büyük ölçüde .NET derlemelerinden özel kod ekleme özelliğine dayanır.

.NET derlemesi kaydetme

CREATE ASSEMBLY U-SQL Veritabanı içine bir .NET derlemesi yerleştirmek için deyimini kullanın. Daha sonra U-SQL betikleri deyimini REFERENCE ASSEMBLY kullanarak bu derlemeleri kullanabilir.

Aşağıdaki kod, bir derlemenin nasıl kaydedileceklerini gösterir:

CREATE ASSEMBLY MyDB.[MyAssembly]
   FROM "/myassembly.dll";

Aşağıdaki kod, bir derlemeye nasıl başvuracaklarını gösterir:

REFERENCE ASSEMBLY MyDB.[MyAssembly];

Bu konuyu daha ayrıntılı bir şekilde kapsayan derleme kayıt yönergelerine başvurun.

Derleme sürümü oluşturma kullanma

U-SQL şu anda .NET Framework 4.7.2 sürümünü kullanmaktadır. Bu nedenle kendi derlemelerinizin çalışma zamanının bu sürümüyle uyumlu olduğundan emin olun.

Daha önce belirtildiği gibi, U-SQL kodu 64 bit (x64) biçiminde çalıştırır. Bu nedenle kodunuzun x64 üzerinde çalışacak şekilde derlendiğinden emin olun. Aksi takdirde, daha önce gösterilen yanlış biçim hatasını alırsınız.

Karşıya yüklenen her derleme DLL'i ve farklı bir çalışma zamanı, yerel derleme veya yapılandırma dosyası gibi kaynak dosyaları en fazla 400 MB olabilir. DAĞıTıLAN kaynakların toplam boyutu( DEPLOY RESOURCE veya derlemelere ve diğer dosyalarına başvurular yoluyla) 3 GB'ı aşamaz.

Son olarak, her U-SQL veritabanı belirli bir derlemenin yalnızca bir sürümünü içerebilir. Örneğin, NewtonSoft Json.NET kitaplığının hem sürüm 7 hem de sürüm 8'e ihtiyacınız varsa, bunları iki farklı veritabanına kaydetmeniz gerekir. Ayrıca, her betik belirli bir derleme DLL'sinin yalnızca bir sürümüne başvurabilir. Bu açıdan U-SQL, C# derleme yönetimi ve sürüm oluşturma semantiğini izler.

Kullanıcı tanımlı işlevleri kullanma: UDF

U-SQL kullanıcı tanımlı işlevler veya UDF, parametreleri kabul eden, bir eylem gerçekleştiren (karmaşık bir hesaplama gibi) ve bu eylemin sonucunu değer olarak döndüren programlama yordamlarıdır. UDF'nin dönüş değeri yalnızca tek bir skaler olabilir. U-SQL UDF, diğer C# skaler işlevleri gibi U-SQL temel betiğinde çağrılabilir.

U-SQL kullanıcı tanımlı işlevleri genel ve statik olarak başlatmanızı öneririz.

public static string MyFunction(string param1)
{
    return "my result";
}

İlk olarak UDF oluşturmanın basit örneğine bakalım.

Bu kullanım örneği senaryosunda, belirli bir kullanıcı için ilk oturum açma işleminin mali çeyreği ve mali ayı da dahil olmak üzere mali dönemi belirlememiz gerekir. Senaryomuzda yılın ilk mali ayı Haziran ayıdır.

Mali dönemi hesaplamak için aşağıdaki C# işlevini tanıtacağız:

public static string GetFiscalPeriod(DateTime dt)
{
    int FiscalMonth=0;
    if (dt.Month < 7)
    {
        FiscalMonth = dt.Month + 6;
    }
    else
    {
        FiscalMonth = dt.Month - 6;
    }

    int FiscalQuarter=0;
    if (FiscalMonth >=1 && FiscalMonth<=3)
    {
        FiscalQuarter = 1;
    }
    if (FiscalMonth >= 4 && FiscalMonth <= 6)
    {
        FiscalQuarter = 2;
    }
    if (FiscalMonth >= 7 && FiscalMonth <= 9)
    {
        FiscalQuarter = 3;
    }
    if (FiscalMonth >= 10 && FiscalMonth <= 12)
    {
        FiscalQuarter = 4;
    }

    return "Q" + FiscalQuarter.ToString() + ":P" + FiscalMonth.ToString();
}

Yalnızca mali ayı ve üç aylık dönemi hesaplar ve bir dize değeri döndürür. İlk mali çeyreğin ilk ayı olan Haziran için "Q1:P1" kullanırız. Temmuz için "Q1:P2" vb. kullanırız.

Bu, U-SQL projemizde kullanacağımız normal bir C# işlevidir.

Bu senaryoda arka planda kod bölümü şöyle görünür:

using Microsoft.Analytics.Interfaces;
using Microsoft.Analytics.Types.Sql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace USQL_Programmability
{
    public class CustomFunctions
    {
        public static string GetFiscalPeriod(DateTime dt)
        {
            int FiscalMonth=0;
            if (dt.Month < 7)
            {
                FiscalMonth = dt.Month + 6;
            }
            else
            {
                FiscalMonth = dt.Month - 6;
            }

            int FiscalQuarter=0;
            if (FiscalMonth >=1 && FiscalMonth<=3)
            {
                FiscalQuarter = 1;
            }
            if (FiscalMonth >= 4 && FiscalMonth <= 6)
            {
                FiscalQuarter = 2;
            }
            if (FiscalMonth >= 7 && FiscalMonth <= 9)
            {
                FiscalQuarter = 3;
            }
            if (FiscalMonth >= 10 && FiscalMonth <= 12)
            {
                FiscalQuarter = 4;
            }

            return "Q" + FiscalQuarter.ToString() + ":" + FiscalMonth.ToString();
        }
    }
}

Şimdi bu işlevi temel U-SQL betiğinden çağıracağız. Bunu yapmak için ad alanı da dahil olmak üzere işlev için ad alanını içeren tam bir ad sağlamamız gerekir. Bu örnekte NameSpace.Class.Function(parametre).

USQL_Programmability.CustomFunctions.GetFiscalPeriod(dt)

Gerçek U-SQL temel betiği aşağıdadır:

DECLARE @input_file string = @"\usql-programmability\input_file.tsv";
DECLARE @output_file string = @"\usql-programmability\output_file.tsv";

@rs0 =
    EXTRACT
        guid Guid,
        dt DateTime,
        user String,
        des String
    FROM @input_file USING Extractors.Tsv();

DECLARE @default_dt DateTime = Convert.ToDateTime("06/01/2016");

@rs1 =
    SELECT
        MAX(guid) AS start_id,
        MIN(dt) AS start_time,
        MIN(Convert.ToDateTime(Convert.ToDateTime(dt<@default_dt?@default_dt:dt).ToString("yyyy-MM-dd"))) AS start_zero_time,
        MIN(USQL_Programmability.CustomFunctions.GetFiscalPeriod(dt)) AS start_fiscalperiod,
        user,
        des
    FROM @rs0
    GROUP BY user, des;

OUTPUT @rs1
    TO @output_file
    USING Outputters.Text();

Betik yürütmesinin çıkış dosyası aşağıdadır:

0d8b9630-d5ca-11e5-8329-251efa3a2941,2016-02-11T07:04:17.2630000-08:00,2016-06-01T00:00:00.0000000,"Q3:8","User1",""

20843640-d771-11e5-b87b-8b7265c75a44,2016-02-11T07:04:17.2630000-08:00,2016-06-01T00:00:00.0000000,"Q3:8","User2",""

301f23d2-d690-11e5-9a98-4b4f60a1836f,2016-02-11T09:01:33.9720000-08:00,2016-06-01T00:00:00.0000000,"Q3:8","User3",""

Bu örnekte U-SQL'de satır içi UDF'nin basit kullanımı gösterilmektedir.

UDF çağrıları arasında durumu koruma

U-SQL C# programlanabilirlik nesneleri, kod arkası genel değişkenleri aracılığıyla etkileşimden yararlanarak daha karmaşık olabilir. Şimdi aşağıdaki iş kullanım örneği senaryosuna göz atalım.

Büyük kuruluşlarda kullanıcılar dahili uygulama türleri arasında geçiş yapabilir. Bunlar Microsoft Dynamics CRM, Power BI vb. içerebilir. Müşteriler, kullanıcıların farklı uygulamalar arasında nasıl geçiş yaptığını, kullanım eğilimlerinin ne olduğunu vb. içeren bir telemetri analizi uygulamak isteyebilir. İşletmenin amacı, uygulama kullanımını iyileştirmektir. Ayrıca farklı uygulamaları veya belirli oturum açma yordamlarını birleştirmek isteyebilirler.

Bu hedefe ulaşmak için oturum kimliklerini ve gerçekleşen son oturum arasındaki gecikme süresini belirlememiz gerekir.

Önceki oturum açma bilgilerini bulmalıyız ve ardından bu oturum açma işlemini aynı uygulamada oluşturulan tüm oturumlara atamalıyız. İlk zorluk, U-SQL temel betiğinin LAG işleviyle önceden hesaplanmış sütunlara hesaplamalar uygulamamıza izin vermemesidir. İkinci zorluk, aynı zaman aralığındaki tüm oturumlar için belirli bir oturumu tutmamız gerekmektir.

Bu sorunu çözmek için arka planda kod bölümü içinde genel bir değişken kullanırız: static public string globalSession;.

Bu genel değişken betik yürütmemiz sırasında satır kümesinin tamamına uygulanır.

U-SQL programımızın arka planda kod bölümü aşağıdadır:

using Microsoft.Analytics.Interfaces;
using Microsoft.Analytics.Types.Sql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace USQLApplication21
{
    public class UserSession
    {
        static public string globalSession;
        static public string StampUserSession(string eventTime, string PreviousRow, string Session)
        {

            if (!string.IsNullOrEmpty(PreviousRow))
            {
                double timeGap = Convert.ToDateTime(eventTime).Subtract(Convert.ToDateTime(PreviousRow)).TotalMinutes;
                if (timeGap <= 60) {return Session;}
                else {return Guid.NewGuid().ToString();}
            }
            else {return Guid.NewGuid().ToString();}

        }

        static public string getStampUserSession(string Session)
        {
            if (Session != globalSession && !string.IsNullOrEmpty(Session)) { globalSession = Session; }
            return globalSession;
        }

    }
}

Bu örnekte, işlevin içinde getStampUserSession kullanılan genel değişken static public string globalSession; ve Session parametresi her değiştirildiğinde yeniden başlatılma işlemi gösterilmektedir.

U-SQL temel betiği aşağıdaki gibidir:

DECLARE @in string = @"\UserSession\test1.tsv";
DECLARE @out1 string = @"\UserSession\Out1.csv";
DECLARE @out2 string = @"\UserSession\Out2.csv";
DECLARE @out3 string = @"\UserSession\Out3.csv";

@records =
    EXTRACT DataId string,
            EventDateTime string,
            UserName string,
            UserSessionTimestamp string

    FROM @in
    USING Extractors.Tsv();

@rs1 =
    SELECT
        EventDateTime,
        UserName,
        LAG(EventDateTime, 1)
            OVER(PARTITION BY UserName ORDER BY EventDateTime ASC) AS prevDateTime,
        string.IsNullOrEmpty(LAG(EventDateTime, 1)
            OVER(PARTITION BY UserName ORDER BY EventDateTime ASC)) AS Flag,
        USQLApplication21.UserSession.StampUserSession
           (
                EventDateTime,
                LAG(EventDateTime, 1) OVER(PARTITION BY UserName ORDER BY EventDateTime ASC),
                LAG(UserSessionTimestamp, 1) OVER(PARTITION BY UserName ORDER BY EventDateTime ASC)
           ) AS UserSessionTimestamp
    FROM @records;

@rs2 =
    SELECT
        EventDateTime,
        UserName,
        LAG(EventDateTime, 1)
        OVER(PARTITION BY UserName ORDER BY EventDateTime ASC) AS prevDateTime,
        string.IsNullOrEmpty( LAG(EventDateTime, 1) OVER(PARTITION BY UserName ORDER BY EventDateTime ASC)) AS Flag,
        USQLApplication21.UserSession.getStampUserSession(UserSessionTimestamp) AS UserSessionTimestamp
    FROM @rs1
    WHERE UserName != "UserName";

OUTPUT @rs2
    TO @out2
    ORDER BY UserName, EventDateTime ASC
    USING Outputters.Csv();

İşlev USQLApplication21.UserSession.getStampUserSession(UserSessionTimestamp) , ikinci bellek satır kümesi hesaplaması sırasında burada çağrılır. Sütunu geçirir UserSessionTimestamp ve değişene kadar UserSessionTimestamp değeri döndürür.

Çıkış dosyası aşağıdaki gibidir:

"2016-02-19T07:32:36.8420000-08:00","User1",,True,"72a0660e-22df-428e-b672-e0977007177f"
"2016-02-17T11:52:43.6350000-08:00","User2",,True,"4a0cd19a-6e67-4d95-a119-4eda590226ba"
"2016-02-17T11:59:08.8320000-08:00","User2","2016-02-17T11:52:43.6350000-08:00",False,"4a0cd19a-6e67-4d95-a119-4eda590226ba"
"2016-02-11T07:04:17.2630000-08:00","User3",,True,"51860a7a-1610-4f74-a9ea-69d5eef7cd9c"
"2016-02-11T07:10:33.9720000-08:00","User3","2016-02-11T07:04:17.2630000-08:00",False,"51860a7a-1610-4f74-a9ea-69d5eef7cd9c"
"2016-02-15T21:27:41.8210000-08:00","User3","2016-02-11T07:10:33.9720000-08:00",False,"4d2bc48d-bdf3-4591-a9c1-7b15ceb8e074"
"2016-02-16T05:48:49.6360000-08:00","User3","2016-02-15T21:27:41.8210000-08:00",False,"dd3006d0-2dcd-42d0-b3a2-bc03dd77c8b9"
"2016-02-16T06:22:43.6390000-08:00","User3","2016-02-16T05:48:49.6360000-08:00",False,"dd3006d0-2dcd-42d0-b3a2-bc03dd77c8b9"
"2016-02-17T16:29:53.2280000-08:00","User3","2016-02-16T06:22:43.6390000-08:00",False,"2fa899c7-eecf-4b1b-a8cd-30c5357b4f3a"
"2016-02-17T16:39:07.2430000-08:00","User3","2016-02-17T16:29:53.2280000-08:00",False,"2fa899c7-eecf-4b1b-a8cd-30c5357b4f3a"
"2016-02-17T17:20:39.3220000-08:00","User3","2016-02-17T16:39:07.2430000-08:00",False,"2fa899c7-eecf-4b1b-a8cd-30c5357b4f3a"
"2016-02-19T05:23:54.5710000-08:00","User3","2016-02-17T17:20:39.3220000-08:00",False,"6ca7ed80-c149-4c22-b24b-94ff5b0d824d"
"2016-02-19T05:48:37.7510000-08:00","User3","2016-02-19T05:23:54.5710000-08:00",False,"6ca7ed80-c149-4c22-b24b-94ff5b0d824d"
"2016-02-19T06:40:27.4830000-08:00","User3","2016-02-19T05:48:37.7510000-08:00",False,"6ca7ed80-c149-4c22-b24b-94ff5b0d824d"
"2016-02-19T07:27:37.7550000-08:00","User3","2016-02-19T06:40:27.4830000-08:00",False,"6ca7ed80-c149-4c22-b24b-94ff5b0d824d"
"2016-02-19T19:35:40.9450000-08:00","User3","2016-02-19T07:27:37.7550000-08:00",False,"3f385f0b-3e68-4456-ac74-ff6cef093674"
"2016-02-20T00:07:37.8250000-08:00","User3","2016-02-19T19:35:40.9450000-08:00",False,"685f76d5-ca48-4c58-b77d-bd3a9ddb33da"
"2016-02-11T09:01:33.9720000-08:00","User4",,True,"9f0cf696-c8ba-449a-8d5f-1ca6ed8f2ee8"
"2016-02-17T06:30:38.6210000-08:00","User4","2016-02-11T09:01:33.9720000-08:00",False,"8b11fd2a-01bf-4a5e-a9af-3c92c4e4382a"
"2016-02-17T22:15:26.4020000-08:00","User4","2016-02-17T06:30:38.6210000-08:00",False,"4e1cb707-3b5f-49c1-90c7-9b33b86ca1f4"
"2016-02-18T14:37:27.6560000-08:00","User4","2016-02-17T22:15:26.4020000-08:00",False,"f4e44400-e837-40ed-8dfd-2ea264d4e338"
"2016-02-19T01:20:31.4800000-08:00","User4","2016-02-18T14:37:27.6560000-08:00",False,"2136f4cf-7c7d-43c1-8ae2-08f4ad6a6e08"

Bu örnekte, bellek satır kümesinin tamamına uygulanan arka planda kod bölümü içinde genel değişken kullandığımız daha karmaşık bir kullanım örneği senaryosu gösterilmektedir.

Sonraki adımlar