1

두 개의 Google 시트 통합 문서가 있습니다.18,000 행 데이터 세트에서 항목을 조회하는 데 스크립트가 11-20 초 걸립니다.

하나는 제조업체 항목 #을 기반으로하는 키가있는 조회 데이터의 "마스터"출처로, 1234에서 A-01/234-Name_1까지 가능합니다. SpreadsheetApp.openByUrl을 통해 참조되는이 시트에는 18,000 개의 행과 13 개의 열이 있습니다. 키 열은 일반 텍스트로 변환되고 시트는이 열로 정렬됩니다.

두 번째는 사람들이 마스터에 대해 조회해야하는 항목 #s를 입력하는 "템플릿"입니다. 일반적으로 한 번에 20 - 1500 개의 항목이 있습니다.

스크립트가 템플릿에 있습니다. 그것은 매우 느리고 일상적으로 30 분 후에 종료됩니다. 다른 사람이 작성했으며 App Script는 처음이지만 스크립트가 수행하는 작업과 병목 현상이 어디에서 발생하는지 파악할 수있었습니다.

그것은 잔뜩 않지만,이 조회의 고기 :()는 내가 루프를 통해 각 시간이 11하고 있음을 결정하기 위해 내가 Logger.log을 사용

var numrows = master.getDataRange().getNumRows(); 
var masterdata = master.getDataRange().getValues(); 
var itemnumberlist = template.getDataRange().getValues(); 
var retreiveddata = [];  
// iterate through the manf item number list to find all matches in the 
// master and return those matches to another sheet 
for (i = 1; i < template.getDataRange().getValues().length; i++) { 
    for (j = 0; j < numrows; j++) { 
    if (masterdata[j][1].toString() === itemnumberlist[i][1].toString()) { 
     retreiveddata.push(data[j]); 
     anothersheet.appendRow(data[j]); 
    } 
    } 
} 

-19초을, 그것은 단지 미친 것처럼 보인다. 나는 몇 가지 구글 검색을 해 봤는데 내가 다른 몇 가지를 시도했습니다

은 ...

우선 스크립트가 모든 일을 할 것이다, 그래서 루프의 발견 데이터의 쓰기를 이동 시도 처음에는 독서를 읽은 다음 하나의 큰 덩어리로 작성했지만 정확하게 얻을 수는 없었습니다. 내 두 시도는 아래 있습니다.

var mycounter = 0; 
for (i = 0; i < template.getDataRange().getValues().length; i++) { 
    for (j = 0; j < numrows; j++) { 
    if (masterdata[j][0].toString() === itemnumberlist[i][0].toString()) { 
     retreiveddata.push(masterdata[j]); 
     mycounter = mycounter + 1; 
    } 
    } 
} 

// Attempt 1 
// var myrange = retreiveddata.length; 
// for(k = 0; k < myrange; k++) { 
// anothersheet.appendRow(retreiveddata.pop([k]); 
// } 

//Attempt 2 
var myotherrange = anothersheet.getRange(2,1,myothercounter, 13) 
myotherrange.setValues(retreiveddata); 

이 금요일 이었기 때문에 나는 확실히 기억할 수없는,하지만 난 둘 다 시도 "anothersheet"로 전체 마스터 파일을 작성하려고 스크립트의 결과라고 생각한다.

그래서 임시로 이것을 설정하고 다른 것을 시도하기로 결정했습니다. 몇 가지 샘플 스프레드 시트에서 문제를 재현하려고했지만 그렇게 할 수 없었습니다. 동일한 스크립트가 조회 당 1 초 미만 내 15,000 행 샘플 "마스터"파일을 통해지고있다. 내가 생각할 수있는 유일한 점은 이상한 텍스트 문자열 대신에 임의의 숫자를 키로 사용했다는 것입니다.

이렇게되면 마스터 데이터와 값 모두에서 해시 알고리즘을 사용할 수 있다고 생각하게되었지만이 문제는 다른 모든 문제를 나타냅니다.

나는 다른 포럼 게시물에서 이러한 기능을 빌린 :

function GetMD5Hash(value) { 
    var rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, 
value); 
    var txtHash = ''; 
    for (j = 0; j <rawHash.length; j++) { 
    var hashVal = rawHash[j]; 
    if (hashVal < 0) 
     hashVal += 256; 
    if (hashVal.toString(16).length == 1) 
     txtHash += "0"; 
    txtHash += hashVal.toString(16); 
    Utilities.sleep(100); 
    } 
    return txtHash; 
} 

function RangeGetMD5Hash(input) { 
    if (input.map) {   // Test whether input is an array. 
    return input.map(GetMD5Hash); // Recurse over array if so. 
    Utilities.sleep(100); 
    } else { 
    return GetMD5Hash(input) 
    } 
} 

는 말 그대로 내 마스터 스프레드 시트에있는 모든 18,000 항목 #S의 해시 값을 얻기 위해 나에게 모든 일을했다. GetMD5Hash 또는 RangeGetMD5Hash는 일관되게 값을 반환하지 않습니다. 한 번에 몇 행만 할 수 있습니다. 때로는 "로드 중 ..."이 무기한으로 표시됩니다. 때로는 "#Name"GetMD5Hash에 대한 메시지가 정의되지 않은 (이전 행에서 작동 했음에도 불구하고) 메시지가 나타납니다. 그리고 때로는 내부 오류에 대한 메시지와 함께 "# 오류"가 발생합니다.

이 방법은 실제로 각 항목의 검색 시간을 2 - 3 초 (훨씬 좋지만 좋지 않음)로 줄입니다. 그러나 입력 데이터를 일관되게 처리 할 수있는 해시 함수를 가져올 수 없습니다.

이 시점에서 나는이 포럼에서 현명한 사람들에게 손을 내밀어 기적 반응에 대한 희망을 줄 수 있다고 생각하면서 다른 작업에 대해 매우 좌절감을 느낀다.

요약하면, 나는이 세 가지 항목에 대한 제안을 찾고 있어요 : 내가 for 루프에서 쓰기를 이동하는 나의 시도에서 잘못하고있는 무슨

  1. ?
  2. 내 해시 값을 더 빨리 얻거나 동일한 목표를 달성하기 위해 다른 방법을 사용할 수 있습니까?
  3. 스크립트의 속도를 높이려면 어떻게해야합니까?

제공 할 수있는 제안 사항에 큰 감사드립니다!

답변

0

당신이합니다 (appendRow를 이동하는 시도로 올바른 접근 방식에 명중처럼 소리 -Mandy

) 루프에서 호출합니다. 스프레드 시트를 읽거나 쓰고있을 때마다 개별 통화가 1 초에서 2 초 정도 걸릴 것으로 예상 할 수 있으므로 일치하는 시간이 많이 걸릴 수 있습니다. 배열에 일치 항목을 저장하고 한꺼번에 모두 쓰는 것이 좋습니다.

내가주의하는 또 다른 사항은 스크립트가 실제 for 루프 조건 명령문에서 getValues ​​()를 호출한다는 것입니다. 루프의 각 반복마다 매번 조건문이 실행되므로 일치하지 않아도 많은 시간을 낭비 할 가능성이 있습니다.

원하는 동작에 따라 도움이 될 수있는 최종 조정. 첫 번째 경기를 찾은 후 inner for 루프를 멈출 수 있습니다. 첫 번째 경기에만 관심이 있거나 하나의 경기 만 알면 반복 횟수를 많이 절약 할 수 있습니다. 이렇게하려면 retreiveddata.push(masterdata[j]); 행 바로 뒤에 "break"을 입력하십시오.

for (i = 1; i < itemnumberlist.length; i++) { 
    for (j = 0; j < numrows; j++) { 
    if (masterdata[j][0].toString() === itemnumberlist[i][0].toString()) { 
     retreiveddata.push(masterdata[j]); 
     break; //stop searching after first match, move on to next item 
    } 
    } 
} 

//make sure you have data to write before trying to write it. 
if(retreiveddata.length > 0){ 
    var myotherrange = anothersheet.getRange(2,1,retreiveddata.length, retreiveddata[0].length); 
    myotherrange.setValues(retreiveddata); 
} 

: 휴식 호출을 포함

for (i = 1; i < itemnumberlist.length; i++) { 

그리고 그것은 appendRow의 문제를 함께 해결하고, :

for (i = 1; i < template.getDataRange().getValues().length; i++) { 

사람 :

는에 getValues ​​문제, 변경을 해결하려면 각 실행마다 "다른 시트"에 같은 시트를 다시 사용하는 경우새 결과를 작성하기 전에 기존 데이터를 지우려면3210을 누르십시오.

문자열을 비교하는 문자열을 비교하는 해싱 방식을 모두 통과하므로 해시 또는 실제 부품 번호인지 여부에 따라 중요한 차이는 기대하지 않을 것입니다.

관련 문제