比方说,我有AA脚本,遍历400个对象的列表。 每个对象具有的任何位置从1到10的特性。 每个属性是一个合理的规模字符串或稍微大的整数。
有没有在这些对象保存到一个ScriptDb VS它们保存到电子表格的性能显著差异(W / O在一个批量操作做)。
比方说,我有AA脚本,遍历400个对象的列表。 每个对象具有的任何位置从1到10的特性。 每个属性是一个合理的规模字符串或稍微大的整数。
有没有在这些对象保存到一个ScriptDb VS它们保存到电子表格的性能显著差异(W / O在一个批量操作做)。
ScriptDb中已被弃用。 不使用。
是的,有一个显著的差异! 巨大! 我不得不承认,这个实验结果并不是我预期的方式。
有了这个数据量,写入到电子表格总是比使用ScriptDb中快得多。
这些实验支持关于在批量操作断言谷歌Apps脚本的最佳实践 。 使用单个电子表格中的数据保存setValues()
调用比线由行快75%,并且两个数量级比细胞通过细胞更快。
在另一方面,建议使用Spreadsheet.flush()
应慎重考虑,由于对性能的影响。 在这些实验中,4000细胞的电子表格的单个写了小于50ms,并添加调用flush()
增加了到610ms -仍然不到一秒钟,但幅度税的命令看起来很荒唐。 调用flush()
为每个行400在示例电子表格所作的操作采取几乎12秒,当仅用了164毫秒没有它。 如果你已经经历了超过最长执行时间错误,则可能受益于两家优化代码和删除调用flush()
所有的时序,推导出所述的技术以下如何测量通过执行功能所花费的时间 。 时间以毫秒为单位。
下面是使用来自五个不同的方法,两个单程结果ScriptDB
,三写入电子表格,都具有相同的源数据。 (400个对象具有5串5号属性)
Spreadsheet.flush()
在这个实验中,从实验1,唯一的区别是,我们叫Spreadsheet.flush()
每个之后setValue/s
电话。 这样做的代价是巨大的,(约700%),但不改变使用速度的原因电子表格在ScriptDb的建议,因为写入到电子表格仍然较快。
注:本实验往往与被杀超过了最大的执行时间 。
您正在阅读这篇文章的interwebs,所以它必须是真实的! 但把它与一粒盐。
如果你想执行(或更好,但改善)这些实验,创建一个空白的电子表格,并复制到其中的一个新的脚本这一点。 这也可以作为一个依据 。
/**
* Run experiments to measure speed of various approaches to saving data in
* Google App Script (GAS).
*/
function testSpeed() {
var numObj = 400;
var numAttr = 10;
var doFlush = false; // Set true to activate calls to SpreadsheetApp.flush()
var arr = buildArray(numObj,numAttr);
var start, stop; // time catchers
var db = ScriptDb.getMyDb();
var sheet;
// Save into ScriptDB, Object at a time
deleteAll(); // Clear ScriptDB
start = new Date().getTime();
for (var i=1; i<=numObj; i++) {
db.save({type: "myObj", data:arr[i]});
}
stop = new Date().getTime();
Logger.log("Elapsed time for ScriptDB/Object test: " + (stop - start));
// Save into ScriptDB, Batch
var items = [];
// Restructure data - this is done outside the timed loop, assuming that
// the data would not be in an array if we were using this approach.
for (var obj=1; obj<=numObj; obj++) {
var thisObj = new Object();
for (var attr=0; attr < numAttr; attr++) {
thisObj[arr[0][attr]] = arr[obj][attr];
}
items.push(thisObj);
}
deleteAll(); // Clear ScriptDB
start = new Date().getTime();
db.saveBatch(items, false);
stop = new Date().getTime();
Logger.log("Elapsed time for ScriptDB/Batch test: " + (stop - start));
// Save into Spreadsheet, Object at a time
sheet = SpreadsheetApp.getActive().getActiveSheet().clear();
start = new Date().getTime();
for (var row=0; row<=numObj; row++) {
var values = [];
values.push(arr[row]);
sheet.getRange(row+1, 1, 1, numAttr).setValues(values);
if (doFlush) SpreadsheetApp.flush();
}
stop = new Date().getTime();
Logger.log("Elapsed time for Spreadsheet/Object test: " + (stop - start));
// Save into Spreadsheet, Attribute at a time
sheet = SpreadsheetApp.getActive().getActiveSheet().clear();
start = new Date().getTime();
for (var row=0; row<=numObj; row++) {
for (var cell=0; cell<numAttr; cell++) {
sheet.getRange(row+1, cell+1, 1, 1).setValue(arr[row][cell]);
if (doFlush) SpreadsheetApp.flush();
}
}
stop = new Date().getTime();
Logger.log("Elapsed time for Spreadsheet/Attribute test: " + (stop - start));
// Save into Spreadsheet, Bulk
sheet = SpreadsheetApp.getActive().getActiveSheet().clear();
start = new Date().getTime();
sheet.getRange(1, 1, numObj+1, numAttr).setValues(arr);
if (doFlush) SpreadsheetApp.flush();
stop = new Date().getTime();
Logger.log("Elapsed time for Spreadsheet/Bulk test: " + (stop - start));
}
/**
* Create a two-dimensional array populated with 'numObj' rows of 'numAttr' cells.
*/
function buildArray(numObj,numAttr) {
numObj = numObj | 400;
numAttr = numAttr | 10;
var array = [];
for (var obj = 0; obj <= numObj; obj++) {
array[obj] = [];
for (var attr = 0; attr < numAttr; attr++) {
var value;
if (obj == 0) {
// Define attribute names / column headers
value = "Attr"+attr;
}
else {
value = ((attr % 2) == 0) ? "This is a reasonable sized string for testing purposes, not too long, not too short." : Number.MAX_VALUE;
}
array[obj].push(value);
}
}
return array
}
function deleteAll() {
var db = ScriptDb.getMyDb();
while (true) {
var result = db.query({}); // get everything, up to limit
if (result.getSize() == 0) {
break;
}
while (result.hasNext()) {
var item = result.next()
db.remove(item);
}
}
}