다음을 통해 공유


Microsoft Fabric Data Engineering용 Microsoft JDBC 드라이버(미리 보기)

비고

이 기능은 미리 보기로 제공됩니다.

JDBC(Java Database Connectivity)는 클라이언트 애플리케이션이 데이터베이스 및 빅 데이터 플랫폼의 데이터에 연결하고 작업할 수 있도록 하는 널리 채택된 표준입니다.

패브릭용 Microsoft JDBC Driver Data Engineering을 사용하면 JDBC 표준의 안정성과 단순성을 통해 Microsoft Fabric에서 Spark 워크로드를 연결, 쿼리 및 관리할 수 있습니다. Microsoft Fabric의 Livy API를 기반으로 하는 이 드라이버는 Java 애플리케이션 및 BI 도구에 안전하고 유연한 Spark SQL 연결을 제공합니다. 이 통합을 사용하면 별도의 Notebook 또는 Spark 작업 정의 아티팩트 없이 Spark 코드를 직접 제출하고 실행할 수 있습니다.

주요 기능

  • JDBC 4.2 준수: JDBC 4.2 사양의 전체 구현
  • Microsoft Entra ID 인증: 대화형, 클라이언트 자격 증명 및 인증서 기반 인증을 포함한 여러 인증 흐름
  • 엔터프라이즈 연결 풀링: 상태 모니터링 및 자동 복구를 사용하는 기본 제공 연결 풀링
  • Spark SQL 네이티브 쿼리 지원: 변환 없이 Spark SQL 문의 직접 실행
  • 포괄적인 데이터 형식 지원: 복합 형식(ARRAY, MAP, STRUCT)을 비롯한 모든 Spark SQL 데이터 형식 지원
  • 비동기 결과 집합 프리페치: 성능 향상을 위한 백그라운드 데이터 로드
  • 회로 차단기 패턴: 자동 재시도를 사용하여 연속 오류로부터 보호
  • 자동 다시 연결: 연결 실패에 대한 투명한 세션 복구
  • 프록시 지원: 엔터프라이즈 환경에 대한 HTTP 및 SOCKS 프록시 구성

필수 조건

Microsoft Fabric Data Engineering용 Microsoft JDBC 드라이버를 사용하기 전에 다음이 있는지 확인합니다.

  • JDK(Java Development Kit): 버전 11 이상(Java 21 권장)
  • Microsoft Fabric 액세스: Microsoft Fabric 작업 영역에 대한 액세스
  • Azure Entra ID 자격 증명: 인증에 적합한 자격 증명
  • 작업 영역 및 Lakehouse ID: 패브릭 작업 영역 및 레이크하우스의 GUID 식별자

다운로드 및 설치

Microsoft JDBC Driver for Microsoft Fabric Data Engineering 버전 1.0.0은 공개 미리 보기 버전이며 Java 11, 17 및 21을 지원합니다. Java 연결 지원을 지속적으로 개선하고 있으며 최신 버전의 Microsoft JDBC 드라이버로 작업하는 것이 좋습니다.

  1. 위의 링크에서 zip 또는 tar 파일을 다운로드합니다.
  2. 다운로드한 파일을 추출하여 드라이버 JAR 파일에 액세스합니다.
  3. JRE 버전과 일치하는 JAR 파일을 선택합니다.
    • Java 11의 경우: ms-sparksql-jdbc-1.0.0.jre11.jar
    • Java 17의 경우: ms-sparksql-jdbc-1.0.0.jre17.jar
    • Java 21의 경우: ms-sparksql-jdbc-1.0.0.jre21.jar
  4. 선택한 JAR 파일을 애플리케이션의 클래스 경로에 추가합니다.
  5. JDBC 클라이언트의 경우 JDBC 드라이버 클래스를 구성합니다. com.microsoft.spark.livy.jdbc.LivyDriver

빠른 시작 예제

이 예제에서는 Microsoft Fabric 데이터 엔지니어링용 Microsoft JDBC 드라이버를 사용하여 Microsoft Fabric에 연결하고 쿼리를 실행하는 방법을 보여 줍니다. 이 코드를 실행하기 전에 필수 구성 요소를 완료하고 드라이버를 설치했는지 확인합니다.

import java.sql.*;

public class QuickStartExample {
    public static void main(String[] args) {
        // Connection string with required parameters
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=2;" +  // Interactive browser authentication
                     "LogLevel=INFO";
        
        try (Connection conn = DriverManager.getConnection(url)) {
            // Execute a simple query
            try (Statement stmt = conn.createStatement();
                 ResultSet rs = stmt.executeQuery("SELECT 'Hello from Fabric!' as message")) {
                
                if (rs.next()) {
                    System.out.println(rs.getString("message"));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

연결 문자열 형식

기본 연결 문자열

Microsoft Fabric Data Engineering용 Microsoft JDBC 드라이버는 다음 연결 문자열 형식을 사용합니다.

jdbc:fabricspark://<hostname>[:<port>][;<parameter1>=<value1>;<parameter2>=<value2>;...]

연결 문자열 구성 요소

구성 요소 Description 예시
프로토콜 JDBC URL 프로토콜 식별자 jdbc:fabricspark://
호스트 이름 Microsoft Fabric 엔드포인트 호스트 이름 api.fabric.microsoft.com
항구 선택적 포트 번호(기본값: 443) :443
매개 변수 세미콜론으로 구분된 키=값 쌍 FabricWorkspaceID=<guid>

연결 문자열 예제

기본 연결(대화형 인증)

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;AuthFlow=2

Spark 리소스 구성을 통해

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;DriverCores=4;DriverMemory=4g;ExecutorCores=4;ExecutorMemory=8g;NumExecutors=2;AuthFlow=2

Spark 세션 속성 사용

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<workspace-id>;FabricLakehouseID=<lakehouse-id>;spark.sql.adaptive.enabled=true;spark.sql.shuffle.partitions=200;AuthFlow=2

Authentication

Microsoft JDBC Driver for Microsoft Fabric Data Engineering은 Microsoft Entra ID(이전의 Azure Active Directory)를 통해 여러 인증 방법을 지원합니다. 인증은 연결 문자열의 매개 변수를 AuthFlow 사용하여 구성됩니다.

인증 흐름

AuthFlow 인증 방법 사용 사례
0 Azure CLI 자격 증명 Azure CLI를 사용한 개발
1 클라이언트 자격 증명(서비스 주체) 자동화/서비스 간 인증
2 대화형 브라우저 대화형 사용자 인증(기본값)
3 SPN 서비스 주체 인증
4 인증서 기반 인증서 기반 서비스 주체 인증
5 액세스 토큰 미리 획득한 액세스 토큰

대화형 브라우저 인증

최적 대상: 개발 및 대화형 애플리케이션

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=2;" +  // Interactive browser authentication
             "AuthTenantID=<tenant-id>;" +  // Optional
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

매개 변수:

  • AuthFlow=2: 대화형 브라우저 인증을 지정합니다.
  • AuthTenantID (선택 사항): Azure 테넌트 ID
  • AuthClientID (선택 사항): 애플리케이션(클라이언트) ID

행동:

  • 사용자 인증을 위한 브라우저 창을 엽니다.
  • 자격 증명은 만료될 때까지 후속 연결에 대해 캐시됩니다.
  • 단일 사용자 애플리케이션에 적합

클라이언트 자격 증명 인증

최적 대상: 자동화된 서비스 및 백그라운드 작업

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=1;" +  // Client credentials authentication
             "AuthClientID=<client-id>;" +
             "AuthClientSecret=<client-secret>;" +
             "AuthTenantID=<tenant-id>;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

필수 매개 변수:

  • AuthFlow=1: 클라이언트 자격 증명 인증을 지정합니다.
  • AuthClientID: Microsoft Entra ID의 애플리케이션(클라이언트) ID
  • AuthClientSecret: Microsoft Entra ID의 클라이언트 암호
  • AuthTenantID: Azure 테넌트 ID

모범 사례:

  • 비밀을 안전하게 저장(Azure Key Vault, 환경 변수)
  • 가능하면 관리 ID 사용
  • 시크릿을 정기적으로 교체

인증서 기반 인증

최적 대상: 인증서 기반 인증이 필요한 엔터프라이즈 애플리케이션

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=4;" +  // Certificate-based authentication
             "AuthClientID=<client-id>;" +
             "AuthCertificatePath=/path/to/certificate.pfx;" +
             "AuthCertificatePassword=<certificate-password>;" +
             "AuthTenantID=<tenant-id>;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

필수 매개 변수:

  • AuthFlow=4: 인증서 기반 인증을 지정합니다.
  • AuthClientID: 애플리케이션(클라이언트) ID
  • AuthCertificatePath: PFX/PKCS12 인증서 파일 경로
  • AuthCertificatePassword: 인증서 암호
  • AuthTenantID: Azure 테넌트 ID

서비스 주체 인증

최적 대상: 헤드리스 환경 및 원격 세션

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=3;" +  // Device code authentication
             "AuthClientID=<client-id>;" +
             "AuthTenantID=<tenant-id>;" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

행동:

  • 콘솔에 디바이스 코드 및 URL 표시
  • 사용자가 URL을 방문하여 코드를 입력합니다.
  • 사용자 확인 후 인증이 완료됨

액세스 토큰 인증

최적 대상: 사용자 지정 인증 시나리오

// Acquire token through custom mechanism
String accessToken = acquireTokenFromCustomSource();

String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=5;" +  // Access token authentication
             "AuthAccessToken=" + accessToken + ";" +
             "LogLevel=INFO";

Connection conn = DriverManager.getConnection(url);

인증 캐싱

드라이버는 성능 향상을 위해 인증 토큰을 자동으로 캐시합니다.

// Enable/disable caching (enabled by default)
String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
             "FabricWorkspaceID=<workspace-id>;" +
             "FabricLakehouseID=<lakehouse-id>;" +
             "AuthFlow=2;" +
             "AuthEnableCaching=true;" +  // Enable token caching
             "AuthCacheTTLMS=3600000";    // Cache TTL: 1 hour

Connection conn = DriverManager.getConnection(url);

구성 매개 변수

필수 매개 변수

이러한 매개 변수는 모든 연결 문자열에 있어야 합니다.

매개 변수 유형 Description 예시
FabricWorkspaceID UUID(범용 고유 식별자) Microsoft Fabric 작업 영역 식별자 <workspace-id>
FabricLakehouseID UUID(범용 고유 식별자) Microsoft Fabric Lakehouse 식별자 <lakehouse-id>
AuthFlow 정수 인증 흐름 유형(0-5) 2

선택적 매개 변수

API 버전 구성

매개 변수 유형 Default Description
FabricVersion String v1 Microsoft Fabric API 버전
LivyApiVersion String 2023-12-01 Livy API 버전

환경 구성

매개 변수 유형 Default Description
FabricEnvironmentID UUID(범용 고유 식별자) None Spark 세션에 대한 환경 항목을 참조하기 위한 패브릭 환경 식별자

Spark 구성

세션 리소스 구성

최적의 성능을 위해 Spark 세션 리소스를 구성합니다.

매개 변수 유형 Default Description 예시
DriverCores 정수 Spark 기본값 드라이버의 CPU 코어 수 4
DriverMemory String Spark 기본값 드라이버에 대한 메모리 할당 4g
ExecutorCores 정수 Spark 기본값 실행기당 CPU 코어 수 4
ExecutorMemory String Spark 기본값 실행기당 메모리 할당 8g
NumExecutors 정수 Spark 기본값 실행기 수 2

Example:

DriverCores=4;DriverMemory=4g;ExecutorCores=4;ExecutorMemory=8g;NumExecutors=2

사용자 지정 Spark 세션 속성

접두 spark. 사를 가진 모든 매개 변수는 Spark 세션에 자동으로 적용됩니다.

Spark 구성 예제:

spark.sql.adaptive.enabled=true
spark.sql.adaptive.coalescePartitions.enabled=true
spark.sql.shuffle.partitions=200
spark.sql.autoBroadcastJoinThreshold=10485760
spark.dynamicAllocation.enabled=true
spark.dynamicAllocation.minExecutors=1
spark.dynamicAllocation.maxExecutors=10
spark.executor.memoryOverhead=1g

네이티브 실행 엔진(NEE):

spark.nee.enabled=true

전체 예제:

jdbc:fabricspark://api.fabric.microsoft.com;FabricWorkspaceID=<guid>;FabricLakehouseID=<guid>;DriverMemory=4g;ExecutorMemory=8g;NumExecutors=2;spark.sql.adaptive.enabled=true;spark.nee.enabled=true;AuthFlow=2

HTTP 연결 풀 구성 설정

최적의 네트워크 성능을 위해 HTTP 연결 풀링을 구성합니다.

매개 변수 유형 Default Description
HttpMaxTotalConnections 정수 100 최대 총 HTTP 연결 수
HttpMaxConnectionsPerRoute 정수 50 경로당 최대 연결 수
HttpConnectionTimeoutInSeconds 정수 30 연결 시간 초과
HttpSocketTimeoutInSeconds 정수 60 소켓 읽기 시간 제한
HttpReadTimeoutInSeconds 정수 60 HTTP 읽기 시간 제한
HttpConnectionRequestTimeoutSeconds 정수 30 풀에서 연결 요청 시간 제한
HttpEnableKeepAlive 불리언 (Boolean) true HTTP keep-alive 활성화
HttpKeepAliveTimeoutSeconds 정수 60 연결 유지 시간 제한
HttpFollowRedirects 불리언 (Boolean) true HTTP 리디렉션을 따르기
HttpUseAsyncIO 불리언 (Boolean) false 비동기 HTTP I/O 사용

Example:

HttpMaxTotalConnections=200;HttpMaxConnectionsPerRoute=100;HttpConnectionTimeoutInSeconds=60

프록시 구성

엔터프라이즈 환경에 대한 HTTP 및 SOCKS 프록시 설정을 구성합니다.

매개 변수 유형 Default Description
UseProxy 불리언 (Boolean) false 프록시 사용
ProxyTransport String http 프록시 전송 유형(http/tcp)
ProxyHost String None 프록시 호스트 이름
ProxyPort 정수 None 프록시 포트
ProxyAuthEnabled 불리언 (Boolean) false 프록시 인증 사용
ProxyUsername String None 프록시 인증 사용자 이름
ProxyPassword String None 프록시 인증 암호
ProxyAuthScheme String basic 인증 체계(basic/digest/ntlm)
ProxySocksVersion 정수 5 SOCKS 버전(4/5)

HTTP 프록시 예제:

UseProxy=true;ProxyTransport=http;ProxyHost=proxy.company.com;ProxyPort=8080;ProxyAuthEnabled=true;ProxyUsername=user;ProxyPassword=pass

SOCKS 프록시 예제:

UseProxy=true;ProxyTransport=tcp;ProxyHost=socks.company.com;ProxyPort=1080;ProxySocksVersion=5

로깅 구성

매개 변수 유형 Default Description
LogLevel String INFO 로깅 수준: 추적, 디버그, 정보, 경고, 오류

Example:

LogLevel=DEBUG

기본 로그 위치:

${user.home}/.microsoft/livy-jdbc-driver/driver.log

사용자 지정 로그 구성: 클래스 경로에서 사용자 지정 log4j2.xml 또는 logback.xml 파일을 사용합니다.


사용 예제

기본 연결

import java.sql.*;

public class BasicConnectionExample {
    public static void main(String[] args) {
        String url = "jdbc:fabricspark://api.fabric.microsoft.com;" +
                     "FabricWorkspaceID=<workspace-id>;" +
                     "FabricLakehouseID=<lakehouse-id>;" +
                     "AuthFlow=2";
        
        try (Connection conn = DriverManager.getConnection(url)) {
            System.out.println("Connected successfully!");
            System.out.println("Database: " + conn.getMetaData().getDatabaseProductName());
            System.out.println("Driver: " + conn.getMetaData().getDriverName());
            System.out.println("Driver Version: " + conn.getMetaData().getDriverVersion());
        } catch (SQLException e) {
            System.err.println("Connection failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

쿼리 실행

단순 쿼리

public void executeSimpleQuery(Connection conn) throws SQLException {
    String sql = "SELECT current_timestamp() as now";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        if (rs.next()) {
            Timestamp now = rs.getTimestamp("now");
            System.out.println("Current timestamp: " + now);
        }
    }
}

필터를 사용하여 쿼리

public void executeQueryWithFilter(Connection conn) throws SQLException {
    String sql = "SELECT * FROM sales WHERE amount > 1000 ORDER BY amount DESC";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        while (rs.next()) {
            int id = rs.getInt("id");
            double amount = rs.getDouble("amount");
            Date date = rs.getDate("sale_date");
            
            System.out.printf("ID: %d, Amount: %.2f, Date: %s%n", 
                            id, amount, date);
        }
    }
}

제한 조건을 사용하는 쿼리

public void executeQueryWithLimit(Connection conn) throws SQLException {
    String sql = "SELECT * FROM customers LIMIT 10";
    
    try (Statement stmt = conn.createStatement();
         ResultSet rs = stmt.executeQuery(sql)) {
        
        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();
        
        // Print column names
        for (int i = 1; i <= columnCount; i++) {
            System.out.print(metaData.getColumnName(i) + "\t");
        }
        System.out.println();
        
        // Print rows
        while (rs.next()) {
            for (int i = 1; i <= columnCount; i++) {
                System.out.print(rs.getString(i) + "\t");
            }
            System.out.println();
        }
    }
}

결과 집합 작업

public void navigateResultSet(Connection conn) throws SQLException {
    String sql = "SELECT id, name, amount FROM orders";
    
    try (Statement stmt = conn.createStatement(
            ResultSet.TYPE_SCROLL_INSENSITIVE,
            ResultSet.CONCUR_READ_ONLY);
         ResultSet rs = stmt.executeQuery(sql)) {
        
        // Move to first row
        if (rs.first()) {
            System.out.println("First row: " + rs.getString("name"));
        }
        
        // Move to last row
        if (rs.last()) {
            System.out.println("Last row: " + rs.getString("name"));
            System.out.println("Total rows: " + rs.getRow());
        }
        
        // Move to specific row
        if (rs.absolute(5)) {
            System.out.println("Row 5: " + rs.getString("name"));
        }
    }
}

큰 결과 집합 처리

public void processLargeResultSet(Connection conn) throws SQLException {
    String sql = "SELECT * FROM large_table";
    
    try (Statement stmt = conn.createStatement()) {
        // Set fetch size for efficient memory usage
        stmt.setFetchSize(1000);
        
        try (ResultSet rs = stmt.executeQuery(sql)) {
            int rowCount = 0;
            while (rs.next()) {
                // Process row
                processRow(rs);
                rowCount++;
                
                if (rowCount % 10000 == 0) {
                    System.out.println("Processed " + rowCount + " rows");
                }
            }
            System.out.println("Total rows processed: " + rowCount);
        }
    }
}

private void processRow(ResultSet rs) throws SQLException {
    // Process individual row
}

준비된 구문 사용

public void usePreparedStatement(Connection conn) throws SQLException {
    String sql = "SELECT * FROM products WHERE category = ? AND price > ?";
    
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        // Set parameters
        pstmt.setString(1, "Electronics");
        pstmt.setDouble(2, 100.0);
        
        try (ResultSet rs = pstmt.executeQuery()) {
            while (rs.next()) {
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                System.out.printf("Product: %s, Price: $%.2f%n", name, price);
            }
        }
    }
}

일괄 처리 작업

public void executeBatchInsert(Connection conn) throws SQLException {
    String sql = "INSERT INTO logs (timestamp, level, message) VALUES (?, ?, ?)";
    
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        conn.setAutoCommit(false);  // Disable auto-commit for batch
        
        // Add multiple statements to batch
        for (int i = 0; i < 1000; i++) {
            pstmt.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
            pstmt.setString(2, "INFO");
            pstmt.setString(3, "Log message " + i);
            pstmt.addBatch();
            
            // Execute batch every 100 statements
            if (i % 100 == 0) {
                pstmt.executeBatch();
                pstmt.clearBatch();
            }
        }
        
        // Execute remaining statements
        pstmt.executeBatch();
        conn.commit();
        
        System.out.println("Batch insert completed successfully");
    } catch (SQLException e) {
        conn.rollback();
        throw e;
    } finally {
        conn.setAutoCommit(true);
    }
}

데이터 형식 매핑

드라이버는 Spark SQL 데이터 형식을 JDBC SQL 형식 및 Java 형식에 매핑합니다.

Spark SQL 형식 JDBC SQL 형식 Java 형식 비고
BOOLEAN BOOLEAN Boolean
BYTE TINYINT Byte
SHORT SMALLINT Short
INT INTEGER Integer
LONG BIGINT Long
FLOAT FLOAT Float
DOUBLE DOUBLE Double
DECIMAL DECIMAL BigDecimal 정밀도 및 배율 유지
STRING VARCHAR String
VARCHAR(n) VARCHAR String
CHAR(n) CHAR String
BINARY BINARY byte[]
DATE DATE java.sql.Date
TIMESTAMP TIMESTAMP java.sql.Timestamp
ARRAY VARCHAR String JSON으로 직렬화됨
MAP VARCHAR String JSON으로 직렬화됨
STRUCT VARCHAR String JSON으로 직렬화됨