简体   繁体   English

数组比在Google Scripts中访问Google表格单元格快多少?

[英]How much faster are arrays than accessing Google Sheets cells within Google Scripts?

How much faster is accessing and manipulating an array in google scripts vs accessing and manipulating data from a google sheet? 在Google脚本中访问和操作数组与访问和操作Google工作表中的数据相比要快多少?

Here's the application: 这是应用程序:

I am working on a program to create a schedule for employees. 我正在制定一个为员工创建计划的计划。 My strategy is to create a list of available employees for each day, randomize the list, and then insert a random employee into each open slot one by one based on specific parameters. 我的策略是创建每天可用员工的列表,随机化列表,然后根据特定参数逐个将随机员工插入每​​个打开的插槽。 Then repeat for each day of the week until the schedule is filled. 然后重复一周中的每一天,直到计划完成。

Sometimes the parameters aren't met given the randomized list, and I need to restart the loop. 有时在给定随机列表的情况下不满足参数,我需要重新启动循环。 On average I'll run ~1100 iterations of the loop until the schedule is filled. 平均而言,我将运行~1100次循环迭代,直到计划被填满。 If the GoogleScript runs >6 min then it results in a timeout of the function and it's stopped automatically. 如果GoogleScript运行> 6分钟,则会导致该功能超时并自动停止。

My function is a mix of accessing data from GoogleSheets and accessing data directly from arrays within the function. 我的功能是访问来自GoogleSheets的数据并直接从函数中的数组访问数据。 In general, would there be a noticeable difference to re-write my function such that all the data is directly stored and manipulated within an array? 一般来说,重写我的函数是否会有明显的差异,以便所有数据都直接在数组中存储和操作?

The impact magnitude will depend on how much reading and writing you are doing. 影响程度将取决于您正在做多少读写。 If a lot of incremental data transfer is currently used, then changing your approach can yield massive benefit. 如果当前使用了大量增量数据传输,那么改变您的方法可以带来巨大的好处。

Calls to the Spreadsheet API generally take 0.01 seconds or more to complete. 调用Spreadsheet API通常需要0.01秒或更长时间才能完成。 Calls that import / export data, or call sub-functions, will take longer (eg getDataRange , getValue(s) , setValue(s) ). 调用导入/导出数据或调用子函数将需要更长时间(例如getDataRangegetValue(s)setValue(s) )。 Apps Script is smart enough to optimize some successive calls, but if you are alternating reads and writes, then nothing on Google's end can help you. Apps脚本非常智能,可以优化一些连续的调用,但如果你是交替读写,那么Google端的任何内容都无法帮助你。
You can view this timing data on the View -> Execution Transcript menu. 您可以在View -> Execution Transcript菜单上查看此计时数据。

My suggestion is to move any existing cell-based validation formulas into script functions that operate on a passed employee name, an object mapping between employees and the shifts they have already "worked", and the proposed shift to work. 我的建议是将任何现有的基于单元格的验证公式移动到脚本函数中,这些函数对传递的员工名称进行操作,员工之间的对象映射以及他们已经“工作”的班次,以及建议的转换工作。 Then you'd be able to use 1 call to import the employee - day availability list, and for each day, for each shift, validate that a randomly chosen available employee can work it, given their previous shifts in the scheduling period. 然后,您可以使用1次呼叫导入员工日可用性列表,并且对于每个班次,每天都要验证随机选择的可用员工是否可以使用它,因为他们之前在调度期间进行了调整。 Lastly, you'd write your object back to the sheet(s). 最后,您将对象写回工作表。


Timing Script (which gets internally optimized by google due to successive reads) 时间脚本(由于连续读取而由谷歌进行内部优化)

function writeRand_(rows, cols)
{
  var datasheet = SpreadsheetApp.openById(ssid).getSheetByName('Sheet1');
  datasheet.getDataRange().clearContent();
  var rand = [];
  for(var row = 0; row < rows; ++row)
  {
    var data = [];
    for(var col = 0; col < cols; ++col)
      data.push(Math.random());
    rand.push(data);
  }
  datasheet.getRange(1, 1, rand.length, rand[0].length).setValues(rand);
  return datasheet;
}

function readAndTime()
{
  var rows = 50, cols = 8;
  var datasheet = writeRand_(rows, cols);
  // sum one-by-one
  var sum1 = 0;
  var startRangeSum = new Date().getTime();
  for(var row = 1; row <= rows; ++row)
    for(var col = 1; col <= cols; ++col)
      sum1 += datasheet.getRange(row, col).getValue()-0;
  var endRangeSum = new Date().getTime();
  // Read all, then sum.
  var sum2 = 0;
  var startArraySum = new Date().getTime();
  var inputs = datasheet.getDataRange().getValues();
  for(var row = 0; row < inputs.length; ++row)
    for(var col = 0; col < inputs[0].length; ++col)
      sum2 += inputs[row][col]-0;
  var endArraySum = new Date().getTime();
  Logger.log("Value count: " + rows * cols);
  Logger.log("Range sum: " + (endRangeSum - startRangeSum)/1000 + " sec. " + sum1);
  Logger.log("Array sum: " + (endArraySum - startArraySum)/1000 + " sec. " + sum2);
}

The above gives me ~.8s for range and .2s for array - and that .2s is essentially all due to the time it takes to call getDataRange() to make inputs 上面给出了~8s的范围和.2s的数组 - 而.2s基本上都是由于调用getDataRange()来进行inputs所需的时间

tehhowch says properly =) I do it like that. tehhowch说得恰当=)我这样做。

/* The first couple of nested loops use only reading methods as well as based on this 
    they pick up cells whose value must be changed in the array for next loop
*/

for (var rowIndex = editedCell.getRow(); rowIndex <= wageGrid.getLastRow(); rowIndex++) {
  if (weBreak) break;

  for (var collIndex = (rowIndex == editedCell.getRow()) ? (editedCell.getColumn() + 1) : wageGrid.getColumn(); collIndex <= wageGrid.getLastColumn(); collIndex++) {

    var cell = aSheet.getRange(rowIndex, collIndex);
    var cellFontColor = cell.getFontColor();
    var cellYearAndMonth = aSheet.getRange(rowIndex, 1).getValue();
    var cellDay = aSheet.getRange(1, collIndex).getValue();

    if (cellFontColor == "#ff0000") {

      weBreak = true;
      break;
    }
    if (aSheet.getRange(rowIndex, 1).getValue().getMonth() == cellYearAndMonth.getMonth()) {

      cellsToSetValue.push(cell);
    }
  }
}

//the next loop has an array of cell and perform only "set" methods

for (var cellIndex = 0; cellIndex <= cellsToSetValue.length; cellIndex++) {

  cellsToSetValue[cellIndex].setValue(evt.value);
}

thus there are only two delays when the API optimizes work of "get" and "set" methods and between them everything happens bearable fast ) 因此,当API优化“获取”和“设置”方法的工作时,只有两个延迟,并且它们之间的一切都快速可忍受)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM