2016-11-10 2 views
3

두 문자열 사이에서 점수를 매기는 간단한 스크립트를 만들었습니다.USQL의 실행 속도가 느림

CN_Matcher.usql 아래 USQL 및 백엔드 .NET 코드를 찾아주세요 :

REFERENCE ASSEMBLY master.FuzzyString; 

@searchlog = 
     EXTRACT ID int, 
       Input_CN string, 
       Output_CN string 
     FROM "/CN_Matcher/Input/sample.txt" 
     USING Extractors.Tsv(); 

@CleansCheck = 
    SELECT ID,Input_CN, Output_CN, CN_Validator.trial.cleanser(Input_CN) AS Input_CN_Cleansed, 
      CN_Validator.trial.cleanser(Output_CN) AS Output_CN_Cleansed 
    FROM @searchlog; 

@CheckData= SELECT ID,Input_CN, Output_CN, Input_CN_Cleansed, Output_CN_Cleansed, 
        CN_Validator.trial.Hamming(Input_CN_Cleansed, Output_CN_Cleansed) AS HammingScore, 
        CN_Validator.trial.LevinstienDistance(Input_CN_Cleansed, Output_CN_Cleansed) AS LevinstienDistance, 
        FuzzyString.ComparisonMetrics.JaroWinklerDistance(Input_CN_Cleansed, Output_CN_Cleansed) AS JaroWinklerDistance 
             FROM @CleansCheck; 

OUTPUT @CheckData 
    TO "/CN_Matcher/CN_Full_Run.txt" 
    USING Outputters.Tsv(); 

CN_Matcher.usql.cs : 나는 100 샘플 배치를 실행 한

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

namespace CN_Validator 
{ 
    public static class trial 
    { 

     public static string cleanser(string val) 
     { 
      List<string> wordsToRemove = "l.p. registered pc bldg pllc lp. l.c. div. national l p l.l.c international r. limited school azioni joint co-op corporation corp., (corp) inc., societa company llp liability l.l.l.p llc bancorporation manufacturing c dst (inc) jv ltd. llc. technology ltd., s.a. mfg rllp incorporated per venture l.l.p c. p.l.l.c l.p.. p. partnership corp co-operative s.p.a tech schl bancorp association lllp n r ltd inc. l.l.p. p.c. co district int intl assn. sa inc l.p co, co. division lc intl. lp professional corp. a l. l.l.c. building r.l.l.p co.,".Split(' ').ToList(); 
      return string.Join(" ", val.ToLower().Split(' ').Except(wordsToRemove)); 
     } 

     public static int Hamming(string source, string target) 
     { 
      int distance = 0; 
      if (source.Length == target.Length) 
      { 
       for (int i = 0; i < source.Length; i++) 
       { 
        if (!source[i].Equals(target[i])) 
        { 
         distance++; 
        } 
       } 
       return distance; 
      } 
      else { return 99999; } 
     } 

     public static int LevinstienDistance(string source, string target) 
     { 
      int n = source.Length; 
      int m = target.Length; 
      int[,] d = new int[n + 1, m + 1]; // matrix 
      int cost; // cost 
      // Step 1 
      if (n == 0) return m; 
      if (m == 0) return n; 
      for (int i = 0; i <= n; d[i, 0] = i++) ; 
      for (int j = 0; j <= m; d[0, j] = j++) ; 
      for (int i = 1; i <= n; i++) 
      { 
       for (int j = 1; j <= m; j++) 
       { 
        cost = (target.Substring(j - 1, 1) == source.Substring(i - 1, 1) ? 0 : 1); 
        d[i, j] = System.Math.Min(System.Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1), 
           d[i - 1, j - 1] + cost); 
       } 
      } 
      return d[n, m]; 
     } 

    } 
} 

입력 및 병렬을 1로 설정하고 우선 순위를 1000으로 설정합니다. 작업이 완료 될 때까지는입니다.

동일한 작업을 1000 개의 입력으로 테스트하고 싶었고 병렬 처리를 1로 설정하고 우선 순위를 1000으로 설정하고 에 대해 100 입력에 대해 1.6 분이 걸렸으므로 1000 입력에는 약 20 분이 걸릴 것이라고 생각했지만 50 분 넘게 실행 중이었고 진행률이 표시되지 않았습니다..

그래서 추가로 100 개의 입력 작업을 추가하고 이전 시간과 동일하게 테스트했습니다. 그래서 나는 평행도를 높이려고 생각하고 그것을 3으로 늘렸고 1 시간 후에도 완료되지 않았다.

는 JOB_ID = 07c0850d-0770-4430-a288-5cddcfc26699 내가 어떤 진행 또는 상태를 볼 수 아니다

주요 문제입니다.

내가 잘못하고 있으면 알려주십시오.

어쨌든 USQL?에서 생성자를 사용할 수 있습니까? 내가 그 일을 할 수 있다면, 나는 반복해서 똑같은 정화 과정을 거칠 필요가 없을 것이다.

답변

2

파일 세트 구문을 사용하여 1000 개의 파일을 지정한다고 가정합니다. 유감스럽게도 파일 세트의 현재 기본 구현은 확장 성이 좋지 않으며 컴파일 (준비) 단계는 (실행과 마찬가지로) 오랜 시간이 걸릴 것입니다. 현재 미리보기에서 더 나은 구현이 있습니다. 제게 마이크로 소프트의 usql 닷컴으로 메일을 보내 주시면 미리보기 구현 방법을 알려 드리겠습니다.

덕분에 마이클

+0

마이클 마이클은 1000 개의 파일이 아니라 1000 개의 입력 파일이 있습니다. 나는 너에게 우편으로 보내 줄 것이다. 응답 해 주셔서 감사합니다. – The6thSense

0

나는이 일을 더 설정 기반 방식으로 바라 보았다. 이에 쉽게 추가 할 수 있도록 예를 들어, 오히려 말을 잡고보다는 코드 숨김 파일에서 제거하는 U-SQL 테이블에 그들을 막을 : 비교를 할 다음

CREATE TABLE IF NOT EXISTS dbo.wordsToRemove 
(
    word string, 

    INDEX cdx_wordsToRemvoe CLUSTERED (word ASC) 
    DISTRIBUTED BY HASH (word) 
); 

INSERT INTO dbo.wordsToRemove (word) 
SELECT word 
FROM (
VALUES 
    ("l.p."), 
    ("registered"), 
    ("pc"), 
    ("bldg"), 
    ("pllc"), 
    ("lp."), 
    ("l.c."), 
    ("div."), 
    ("national"), 
    ("l"), 
    ("p"), 
    ("l.l.c"), 
    ("international"), 
    ("r."), 
    ("limited"), 
    ("school"), 
    ("azioni"), 
    ("joint"), 
    ("co-op"), 
    ("corporation"), 
    ("corp.,"), 
    ("(corp)"), 
    ("inc.,"), 
    ("societa"), 
    ("company"), 
    ("llp"), 
    ("liability"), 
    ("l.l.l.p"), 
    ("llc"), 
    ("bancorporation"), 
    ("manufacturing"), 
    ("c"), 
    ("dst"), 
    ("(inc)"), 
    ("jv"), 
    ("ltd."), 
    ("llc."), 
    ("technology"), 
    ("ltd.,"), 
    ("s.a."), 
    ("mfg"), 
    ("rllp"), 
    ("incorporated"), 
    ("per"), 
    ("venture"), 
    ("l.l.p"), 
    ("c."), 
    ("p.l.l.c"), 
    ("l.p.."), 
    ("p."), 
    ("partnership"), 
    ("corp"), 
    ("co-operative"), 
    ("s.p.a"), 
    ("tech"), 
    ("schl"), 
    ("bancorp"), 
    ("association"), 
    ("lllp"), 
    ("n"), 
    ("r"), 
    ("ltd"), 
    ("inc."), 
    ("l.l.p."), 
    ("p.c."), 
    ("co"), 
    ("district"), 
    ("int"), 
    ("intl"), 
    ("assn."), 
    ("sa"), 
    ("inc"), 
    ("l.p"), 
    ("co,"), 
    ("co."), 
    ("division"), 
    ("lc"), 
    ("intl."), 
    ("lp"), 
    ("professional"), 
    ("corp."), 
    ("a"), 
    ("l."), 
    ("l.l.c."), 
    ("building"), 
    ("r.l.l.p"), 
    ("co.,") 
) AS words(word); 

, 나는 원래 문구를 분할

//DECLARE @inputFile string = "input/input.csv"; // 500 companies, Standard & Poor 500 companies from wikipedia 
DECLARE @inputFile string = "input/input2.csv"; // 850,000 companies, part 1 of extract from Companies House 


@searchlog = 
    EXTRACT id int, 
      Input_CN string, 
      Output_CN string 
    FROM @inputFile 
    USING Extractors.Csv(silent : true); 
    //USING Extractors.Csv(skipFirstNRows:1); 


// Split the input string to remove unwanted words 
@Input_CN = 
    SELECT id, 
      new SQL.ARRAY<string>(Input_CN.Split(' ')) AS splitWords 
    FROM @searchlog; 


@Output_CN = 
    SELECT id, 
      new SQL.ARRAY<string>(Output_CN.Split(' ')) AS splitWords 
    FROM @searchlog; 


// Remove unwanted words from input string 
@Input_CN = 
    SELECT * 
    FROM 
    (
     SELECT o.id, 
       x.splitWord.ToLower() AS splitWord 
     FROM @Input_CN AS o 
      CROSS APPLY 
       EXPLODE(splitWords) AS x(splitWord) 
    ) AS y  
    ANTISEMIJOIN 
     dbo.wordsToRemove AS w 
    ON y.splitWord == w.word; 

// Remove unwanted words from output string 
@Output_CN = 
    SELECT * 
    FROM 
    (
     SELECT o.id, 
       x.splitWord.ToLower() AS splitWord 
     FROM @Output_CN AS o 
      CROSS APPLY 
       EXPLODE(splitWords) AS x(splitWord) 
    ) AS y 
    ANTISEMIJOIN 
     dbo.wordsToRemove AS w 
    ON y.splitWord == w.word; 




// Put the input string back together again 
@Input_CN = 
    SELECT id, 
      String.Join(" ", ARRAY_AGG (splitWord)) AS Input_CN_Cleansed 
    FROM @Input_CN 
    GROUP BY id; 


@Output_CN = 
    SELECT id, 
      String.Join(" ", ARRAY_AGG (splitWord)) AS Output_CN_Cleansed 
    FROM @Output_CN 
    GROUP BY id; 



@output = 
    SELECT i.id, 
      i.Input_CN_Cleansed, 
      o.Output_CN_Cleansed, 
      CN_Validator.trial.Hamming(i.Input_CN_Cleansed, o.Output_CN_Cleansed) AS HammingScore, 
      CN_Validator.trial.LevinstienDistance(i.Input_CN_Cleansed, o.Output_CN_Cleansed) AS LevinstienDistance 
    FROM @Input_CN AS i 
     INNER JOIN 
      @Output_CN AS o 
     ON i.id == o.id; 



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

나는 성능이 비슷하지만, 아마도 디자인을 더 유지 보수입니다 발견 : 최대, 함께 다시 이런 일을 우리가 다시 문구를 넣어 원하지 않는 단어를 제거했다. 어쨌든 내 코드는 850 + k 레코드가 아니라 50 분이 아닌 몇 분만에 실행 중이므로 다른 문제가있을 수 있습니다. 주의 : FuzzyString 라이브러리가 누락되어 테스트에 포함되지 않았습니다. 차이점을 설명 할 수 있습니다.

Microsoft의 업데이트가 있으면이 스레드에 다시 게시하십시오. 원하는 경우 답변으로 표시해주십시오.

+0

이 문제에 대한 해결책을 얻었다면 반드시 여기에 게시 할 것입니다. 코드를 개조 해 주셔서 감사합니다. SQL에서 정규화하는 것은 좋지 않기 때문에 .net 끝내기를 생각했지만 코드는 유지 보수 가능하며 USQL의 모든 기능을 사용하고있는 것처럼 보입니다. – The6thSense