【问题标题】:Google Apps script setValues() issue: timing out intermittentlyGoogle Apps 脚本 setValues() 问题:间歇性超时
【发布时间】:2021-03-06 16:14:31
【问题描述】:

我有一个 Google Apps 脚本已经运行了 4 年,没有出现任何问题。但是,自从 3 周以来,我遇到了这个问题:脚本运行了很长时间并且失败了。这发生在每 10 次运行中的 3 次。错误消息是“服务电子表格在访问 ID 为 [此处为电子表格 ID] 的电子表格时超时”

实际的脚本是复杂的(数千行)并在数百个电子表格上运行,使用fetchUrl() 获取数据并使用setValues() 填充工作表。这个实际的脚本过去可以在 10 张工作表的电子表格上正常工作,并且可以在过去 4 年中毫无问题地更新每张工作表中的 180k 单元格。现在,我连一张表都更新不了。

下面的脚本复制了这个问题:它使用.getValues().setValues()将 1300 行 x 140 列从 Sheet1 复制到 Sheet2。当行数增加到 800 以上时,脚本开始失败。当它运行良好时执行日志显示需要 8 秒。当它失败时,日志显示最多 900 秒的运行时间。在此期间,您无法访问电子表格的时间超过 10 分钟,如果您尝试将电子表格加载到其他选项卡中,则它根本不会加载。

我已经向 Google 支持提出了一个问题,但我没有时间表,但对于给您带来的不便深表歉意。这发生在我尝试过脚本的所有域上,不仅仅是我的域。您需要尝试运行脚本 10 次才能看到失败。

如果有人能提出解决方法或提供有关此问题的一些见解,我将不胜感激。

这里是复制问题的电子表格的链接:https://docs.google.com/spreadsheets/d/1jea15rtjv85YIZumABMfFKESb2_QmX0-7zC-KchWeDc/edit?usp=sharing

function myFunction() {
  var row1 = 1;
  var col1 = 1;
  var row2 = 1300;
  var col2 = 140;
  console.log({numrows:row2, numcols:col2} );
  var rng = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(row1,col1,row2,col2);
  var values_to_set = rng.getValues();
  var rng2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange(row1,col1,row2,col2);
  rng2.setValues(values_to_set);
  console.log('done');
  
}

【问题讨论】:

  • 嗯,您正在复制 182k 值。我想这可能需要一些时间,但我希望它能够在时限内完成。如果文件已经足够大,它可能会影响整体性能。
  • 感谢您的评论,@Marios!它曾经在更大的工作表上工作得很好,每张有 10 张 180k 单元格。您知道可以使用 setValues() 设置的单元格数量的配额吗?问题不在于性能低下,而是脚本失败以及超过 10 分钟无法访问电子表格。
  • 一种解决方法而不是实际的解决方案只是创建文件的副本并使用它。希望这会在一段时间内解决这个问题。
  • @Marios,我认为我的解释可能不清楚,但这只是一个复制问题的虚拟脚本。实际代码要复杂得多,适用于数百个电子表格。也许我应该在我原来的问题中澄清这一点。
  • 我得到了类似的结果。我想我可能会避免使用电子表格进行此操作。

标签: google-apps-script google-sheets server-error request-timed-out


【解决方案1】:

这个问题是already reported to Google in Issuetracker。为问题添加星号(左上角),以请求 Google 开发人员确定问题的优先级并进行修复。


同时,考虑使用高级 Google 服务,使用 对电子表格执行大量操作。


问题似乎源于set* 方法。在您的特定情况下,另一种选择是使用range.copyTo(而不是getValues()setValues()),它可以正常工作(最多测试15 次)

/**@OnlyCurrentDoc*/
function myFunction() {
  var row1 = 1;
  var col1 = 1;
  var row2 = 1300;
  var col2 = 140;
  console.log({numrows:row2, numcols:col2} );
  var rng = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(row1,col1,row2,col2);
  /*var values_to_set = rng.getValues();*/
  var rng2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange(row1,col1,row2,col2);
  /*rng2.setValues(values_to_set);*/
  /*Added*/rng.copyTo(rng2, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false)
  console.log('done');
}


function test_myFunction(i=15){
  while(i--){
    myFunction();
  }
}

【讨论】:

  • 感谢您的建议,@themaster。在我来这里寻找解决方法之前,我确实为这个问题加注了星标。我还向 Google 提交了支持请求,但在几周没有消息后,他们告诉我他们无法复制它。我无法使用您回答中建议的解决方法,因为我从生产中的 fetchUrl 获取数据,而不是从另一张表中获取数据。我将该编辑添加到我的原始帖子中。
  • @NincaTirtil 我明白了。我建议的第一个解决方法仍然是使用 sheet api + 高级 Google 服务,这在另一个答案中进行了详细说明。
【解决方案2】:

根据这个comparison of read/write methods,用advanced services写比setValues()快。

使用原始 sn-p 的以下修改版本适用于您的示例电子表格:

function myFunction() {
  var row1 = 1;
  var col1 = 1;
  var row2 = 1300;
  var col2 = 140;
  Logger.log({numrows:row2, numcols:col2} );
  var rng = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange(row1,col1,row2,col2);
  var values_to_set = rng.getValues();
  var rng2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange(row1,col1,row2,col2);
  //rng2.setValues(values_to_set);
  // Based on https://developers.google.com/apps-script/advanced/sheets
  var request = {
    'valueInputOption': 'USER_ENTERED',
    'data': [
      {
        'range': 'Sheet2!' + rng2.getA1Notation(),
        'majorDimension': 'ROWS',
        'values': values_to_set
      }
    ]
  };
  Sheets.Spreadsheets.Values.batchUpdate(request, SpreadsheetApp.getActiveSpreadsheet().getId());
  Logger.log('done');
}

【讨论】:

  • 感谢您的回答,@mshcruz。这是迄今为止最有用的解决方法。我不知道我可以通过 Google Apps 脚本使 Sheets API 工作,您的示例非常有帮助。我会再测试一下我的代码,如果没有其他有用的答案,我会检查这个作为答案。
【解决方案3】:

google v8 引擎似乎有问题。我最近遇到了同样的问题。禁用 v8 引擎后,它现在可以正常工作了。

转到工具->脚本编辑器。 在脚本编辑器窗口中,单击运行,然后禁用 v8 引擎。见附件。

【讨论】:

  • 根据跟踪器中的comment#4,这也发生在rhino引擎中。
  • 谢谢你,@Mahendra Geete。不幸的是,这也发生在我们的两个引擎中。
  • 我通过禁用 v8 得到了改进,所以这个答案是相关的。我仍然偶尔会收到错误,但频率低于 v8。然而,v8 提供了其他显着的好处,尤其是更新版本的 javascript,所以我已经恢复了它,并且必须坚持解决那里的超时问题。但是请注意,它仍然是(2020 年 12 月)issuetracker.google.com/issues/156530211 中未解决的错误
【解决方案4】:

我在将十几条记录插入到 150k 行的工作表中时遇到了同样的问题。它会读取第一个文件,插入,然后在第二个或第三个文件上失败。我在此工作表中有几个选项卡执行一些非常复杂的嵌套查询和 arrayformula vlookups,并将工作表设置设置为每分钟更新一次。
我的解决方案——解决了这个问题,是用复杂的查询复制我的原始工作表,并用 importRange 替换源数据选项卡(从原始数据表中提取数据)。然后,我从原始数据表中删除了所有其他选项卡。保持原始数据表与动态计算隔离。 简短的回答:删除带有复杂查询、数组公式和 vlookup 的选项卡到另一张表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多