我们有一个使用Google Cloud SQL表的Google App Maker应用。我们的位置在中欧的布拉格,app.saveRecords()最少需要240ms。我们已经尝试了许多方法,包括更改实例的位置,但是并不能解决问题。
幸运的是,解决方案是分批插入新记录。我以前的线程[Google App Maker saving records to DB is taking 240ms per record]中的答案很好地解决了这个问题。
如果有人为我们提供了一个简单的代码来批量更新数据库中的记录[服务器端脚本],我们将非常感激。这样,我们不仅可以批量插入全新的记录,而且可以快速更新已经保存在数据库中的记录数据。
假设我们有一个包含3个自定义字段的数据库:
product code | product availability | price
+ 带有数据的示例数组:
ourData[0] = ['pc001','in stock','99'];
ourData[1] = ['pc002','out of stock','49'];
ourData[2] = ['pc003','out of stock','199'];
ourData[3] = ['pc004','in stock','149'];
ourData[4] = ['pc005','in stock','299'];
...,我们想使用键“产品代码”将可用性和价格数据分配给特定的数据库行。如果在数据库中找不到产品代码,那么我们将新记录插入数据库。
多次单行插入/更新会使EU中的Google App Maker用户花费太长时间,因为即使SQL实例位于欧盟中,查询也确实会转到美国。批量运行此程序可能会打破当今美国以外的Google App Maker限制。非常感谢您为使Google App Maker成为全球初学者的绝佳工具所提供的帮助。
答案 0 :(得分:2)
在线程中其他人的帮助下,我设法将插入或更新记录的时间减少到50ms。此外,我测试了将10000条记录插入/更新到包含60个字段的表中。在这种情况下,每条记录的速度为60ms。在此,我向任何人(可能会觉得有用)提供我的最终代码。感谢您提供所有有用的答案和评论!
/* We use Google Cloud SQL Table "testDB" that contains these fields:
- Id (the default primary key for DBs in Google App Maker)
- productCode
- availability
- price
We have an array called "data" which contains the data [productCode, availability, price] we want to save to the database.
*/
function saveDataNew(){
var data = [];
data[0] = ['pc1','in stock','99'];
data[1] = ['pc2','out of stock','129'];
data[2] = ['pc3','in stock','78'];
data[3] = ['pc4','in stock','95'];
//load all the records in the DB (no filter is used)
var query = app.models.testDB.newQuery();
var records = query.run();
console.log("Found " + records.length + " records in the database.");
//create an array to help us find DB's Id for each unique productCode.
var helpingArray = [];
for (var x in records) {
var product = records[x]; //get each record in the DB
helpingArray.push([product.productCode,product.Id]); //save this record's productCode and Id into the helping array
}
//setting up the writing in batches
var totalRecords = data.length;
var batchLimit = 500; //size of a batch round - number of lines for each app.saveRecords();
var roundlimit;
if(totalRecords < batchLimit){
roundlimit = totalRecords;
}
else{
roundlimit = batchLimit;
}
var totalRounds = Math.ceil(totalRecords / batchLimit);
var round = 1;
var currentItem = 0;
//start writing in batches
do{
var recordsToSave = [];
//create or update a record in the DB for each line of our data within one batch round
for(var i=currentItem; i<roundlimit; i++){
var wantedCode = data[i][0]; //get the productCode of the current line of the data array
var orderNum = -1; //create a variable to find the order number of the productCode in the helping array
for(var z=0; z<helpingArray.length; z++){ //search for the productCode in the helping array
if(helpingArray[z][0]==wantedCode){
orderNum = z; //save the line's number if the productCode is found in the helpingArray
continue;
}
}
var productRecord;
if (orderNum == -1){ //there was no line with the productCode found the helpingArray => create a new record
productRecord = app.models.testDB.newRecord();
productRecord.productCode = data[i][0];
}
else{ //the productCode was found in the helpingArray => edit the existing record in the DB
productRecord = records[orderNum];
}
//provide the record with the data
productRecord.availability = data[i][1];
productRecord.price = data[i][2];
//cumulate records and save them once the batch round is finished
recordsToSave.push(productRecord);
}
//a batch round has been finished, save records if there are any
if(recordsToSave.length){
console.log("Records saved: "+recordsToSave.length);
app.saveRecords(recordsToSave);
}
currentItem += batchLimit;
round++;
if (totalRecords < round*batchLimit){
roundlimit = totalRecords;
}
else{
roundlimit += batchLimit;
}
} while(round <= totalRounds);
}
答案 1 :(得分:0)
可以使用适当的服务器脚本来解决此问题,我强烈建议您阅读official documentation中的服务器脚本的工作方式。请密切注意查询记录示例。
因此,以前面的解决方案示例为基础,可以对其进行略微修改以实现您的需求。这是它的外观:
function saveData(){
//get the data
var data = getData();
var totalRecords = data.length;
var batchLimit = 2000;
var totalRounds = Math.ceil(totalRecords / batchLimit);
var round = 1;
var roundlimit = batchLimit;
var currentItem = 0;
do{
var recordsToSave = [];
for(var i=currentItem; i<roundlimit; i++){
var recordData = data[i];
var productCode = recordData[0];
//check if the record already exists
var query = app.models.testDB.newQuery();
query.filters.productCode._equals = productCode;
var productRecord = query.run()[0];
//if non existent, create a new one
if(!productRecord){
productRecord = app.models.testDB.newRecord();
productRecord.productCode = productCode;
}
productRecord.availability = recordData[1];
productRecord.price = recordData[2];
recordsToSave.push(newProduct);
}
if(recordsToSave.length){
app.saveRecords(recordsToSave);
}
currentItem += batchLimit;
roundlimit += batchLimit;
round++;
} while(round <= totalRounds);
}