2016-11-02 4 views
2

나는 두 개의 파일에 걸쳐있는 많은 양의 데이터를 가지고 있습니다. 분명히, 인코딩 문제가 있습니다 (대부분 UTF-8이지만 분명히 일부 문자는 유효하지 않습니다). https://msdn.microsoft.com/en-us/library/azure/mt764098.aspx에 따르면 인코딩 오류가있는 경우 침묵 플래그를 true로 설정하는 것과 관계없이 런타임 오류가 발생합니다 (오류 행을 건너 뛰는 것을 목표로 함).USQL에 사용자 지정 추출기를 작성하여 인코딩 문제가있는 행을 건너 뜁니다.

그 결과 사용자 지정 추출기를 작성해야합니다. 필자는 https://blogs.msdn.microsoft.com/data_otaku/2016/10/27/a-fixed-width-extractor-for-azure-data-lake-analytics/에 단순화 된 버전의 예제를 작성했습니다. 단지 행을 가져와 구분 기호로 나누고 try 블록 내에서 값을 반환한다는 것입니다. 예외가있는 경우, 나는 그들을 처리하고 계속 진행합니다.

불행히도 USQL 스크립트 자체에서이 추출기를 실제로 참조하는 데 문제가 있습니다. 위의 링크에 대한 지침을 따르면 다른 어셈블리에 논리를 작성하고이를 작성하고 ADLS 데이터베이스/어셈블리에 등록한 다음 스크립트 맨 위에 REFERENCE ASSEMBLY MyExtractors;을 통해 포함하는 것이 좋습니다 (사용 된 네임 스페이스이므로) . 아래의 using 문에서 USING new SimpleExtractor();으로 호출합니다. 이렇게하면 type or namespace cannot be found 인 ADLS 서비스에 대해 스크립트를 실행할 때 오류가 발생합니다. 또한 더 정확 해지고 using 문에 USING new MyExtractors.SimpleExtractor();을 사용하면 위의 USING 문을 인용하여 같은 오류가 발생합니다.

그런 다음 이전 소스에서 https://azure.microsoft.com/en-us/documentation/articles/data-lake-analytics-u-sql-develop-user-defined-operators/이라는 동일한 설명서가 있지만 코드 숨김 파일에서 추가 문서를 찾았습니다. 별도의 어셈블리를 삭제하고 해당 파일의 논리로 논리를 복사했습니다. # 6 단계의 예제에서는 REFERENCE ASSEMBLY 문을 표시하지 않지만 실행하면 다시 type or namespace name cannot be found이라는 오류가 발생합니다.

가장 최근의 릴리스 정보를 보시려면 여기에 뭔가가 지나치게 구식 인데요, 내가 볼 수있는 유일한 것은 USING 문을 사용하면 사용자 정의 코드의 어셈블리에 대한 참조가 필요하다는 것입니다. 시도하기 전에) 실제로 사용하고 있습니다.

누구든지 USQL에서 UDO를 올바르게 참조하는 방법에 대한 지침을 제공하거나 런타임 인코딩 인코딩 예외를 자동으로 처리하는 방법을 알려줄 수 있습니까?

using System.Collections.Generic; 
using System.IO; 
using System.Text; 
using Microsoft.Analytics.Interfaces; 

namespace Utilities 
{ 
    [SqlUserDefinedExtractor(AtomicFileProcessing = true)] 
    public class ModifiedTextExtractor : IExtractor 
    { 
     //Contains the row 
     private readonly Encoding _encoding; 
     private readonly byte[] _row_delim; 
     private readonly char _col_delim; 

     public ModifiedTextExtractor() 
     { 
      _encoding = Encoding.UTF8; 
      _row_delim = _encoding.GetBytes("\r\n"); 
      _col_delim = '\t'; 
     } 

     public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output) 
     { 
      //Read the input line by line 
      foreach (var current in input.Split(_row_delim)) 
      { 
       using (var reader = new StreamReader(current, this._encoding)) 
       { 
        var line = reader.ReadToEnd().Trim(); 

        //If there are any single or double quotes in the line, escape them 
        line = line.Replace(@"""", @"\"""); 

        var count = 0; 

        //Split the input by the column delimiter 
        var parts = line.Split(_col_delim); 

        foreach (var part in parts) 
        { 
         output.Set<string>(count, part); 
         count += 1; 
        } 
       } 
       yield return output.AsReadOnly(); 
      } 
     } 
    } 
} 

내가 (어셈블리로 등록 후) USQL 문에서 사용하기 위해 노력하고있어 방법의 조각 :

은 여기 내 논리가 추출 자체처럼 찾고 무엇

REFERENCE ASSEMBLY [Utilities]; 

CREATE VIEW MyView AS ... 
USING new Utilities.ModifiedTextExtractor(); 

고맙습니다!

+1

친애하는 Xaniff UDO C# 코드에서 사용하는 네임 스페이스/클래스 이름을 표시 할 수 있습니까? 내가 생각하기에 추출기를 공개 정적으로 표시하는 것을 잊었거나 Extractor 클래스 이름에 오타가있는 것으로 가정합니다. –

+0

@MichaelRys 질문에 구현 된 코드가 추가되었습니다. - 감사합니다! – Xaniff

답변

2

VIEW에서 사용자 지정 코드를 참조 할 수 없다는 문제가 발생합니다. U-SQL에서 모든 객체는 컨텍스트 스펙을 포함해야합니다 (예 : 참조 된 어셈블리가 본문에 포함되어 있어야합니다. 이렇게하면 객체 자체가 더욱 복잡해지며 객체의 사용자에게 알려지지 않은 잠재적으로 긴 종속성을 가져 오는 문제를 피할 수 있습니다)

당신이 테이블 반환 함수로 VIEW를 돌고해야 할 일은 :. 다음과 같은 기능을

CREATE FUNCTION MyFunct(/* optional parameters */) RETURNS @res AS 
BEGIN 
    REFERENCE ASSEMBLY [Utilities]; 
    @res = EXTRACT ... USING new Utilities.ModifiedTextExtractor(); 
END; 

그리고 전화 (당신이 SELECT 문에서 행 집합 별칭을 제공 할 필요가 있습니다) :

@data = SELECT ... FROM MyFunct() AS f WHERE ...; 

또는 당신은 프로젝션 필터를 적용하지 않으려면 : 테이블 값 함수가 인라인 될 전망처럼

@data = MyFunct(); 

합니다.

0

이 문제에 대한 또 다른 방법은 행 거부를 지원하는 Azure SQL 데이터웨어 하우스 및 Polybase를 사용하는 것입니다.

1 ) 외부 파일에 ADW에서 외부 테이블을 만듭니다

CREATE EXTERNAL TABLE ext.mycsv (
    colA INT NOT NULL, 
    colB INT NOT NULL, 
    colC INT NOT NULL 
) 
WITH (
    DATA_SOURCE = eds_mycsv, 
    LOCATION = N'/myblobstorage/', 
    FILE_FORMAT = eff_csv, 
    REJECT_TYPE = VALUE, 
    REJECT_VALUE = 1 
) 

외부 테이블 내 예에서와 같이 sinlge 파일이나 디렉토리 (동일한 구조를 가진 여러 개의 파일을 가리 수 있습니다.) reject_value가 1이면 전체 작업을 실패하지 않고 하나의 행이 실패 할 수 있습니다. 이것은 또한 "전체로드를 실패하지 않고 행의 3 %가 실패하는 것을 허용하는 백분율 일 수 있습니다.이 문은 실패한 행에 대한 정보도 제공합니다"REJECT_TYPEREJECT_VALUEhere에 대해 자세히 읽으십시오.

ADW의 또 다른 장점은 사용하지 않을 때 일시 중지 될 수 있다는 것입니다.

2) "에 외부 데이터 소스를 사용하여, 예를 들어

CREATE TABLE dbo.mycsv 
WITH 
( 
    CLUSTERED COLUMNSTORE INDEX, 
    DISTRIBUTION = ROUND_ROBIN 
) 
AS 
SELECT * FROM ext.mycsv; 

3) U-SQL과 푸른 데이터 호수 분석 (ADLA) 내에서 외부 테이블을 만들고, 그것을 실현하기 위해 ADW에서 내부 테이블 만들기 그것이 사는 곳의 쿼리 데이터 "즉, 창고에 저장됩니다.

// Create external table which is in SQL DW 
CREATE EXTERNAL TABLE IF NOT EXISTS adlaExt.mycsv 
(
    colA  int, 
    colB  int, 
    colC  int 
) 
FROM ds_adw LOCATION "dbo.mycsv"; 

4) 예를 들어, U-SQL에서 외부 테이블을 조회 :

// Query external table 
@e = 
    SELECT * 
    FROM dbo.mycsv; 


// Join with internal table 
@q = 
    SELECT a.*, b.someColumn 
    FROM @e AS a 
      INNER JOIN 
       dbo.someOtherTable AS b 
      ON a.colA == b.n_colA; 


// Output it 
OUTPUT @q TO "/output/output.csv" 
USING Outputters.Csv(); 

가 선택적으로 ADLA에 가져옵니다. ADLA here의 통합 쿼리 설정에는 Jorg Klein의 훌륭한 블로그 게시물이 있습니다.

IMHO 이것은 네이티브 Azure 구성 요소를 사용하는 것처럼 사용자 정의 익스 터러를 만드는 것보다 훨씬 안전합니다. Polybase는 아직 ADLA를 지원하지 않지만 향후 어느 시점에서 거의 확실하게 수행 할 것입니다.이 시점에서 설계가 단순화 될 수 있습니다.