如何优化我的 Google 脚本以更快地检索 SQL 数据?

Posted

技术标签:

【中文标题】如何优化我的 Google 脚本以更快地检索 SQL 数据?【英文标题】:How can I optimize my Google Script to retrieve SQL data quicker? 【发布时间】:2019-03-12 18:00:44 【问题描述】:

我对谷歌脚本相当陌生,我正在尝试尽快将 SQL 数据导入谷歌电子表格。

我一直在使用这个脚本:

function readItems()     
  var conn = Jdbc.getConnection("jdbc:sqlserver://server","UN","PW");
  var stmt = conn.createStatement();
  var rs = stmt.executeQuery("SELECT * FROM [dbo].[PriceList]WHERE [Product Line]<>'AL' AND [Product Line]<>'EL' AND [Product Line]<>'Accessories'ORDER BY [Product Line],Family,[Item Code]");

  var doc = SpreadsheetApp.getActive().getSheetByName('Data');
  var cell = doc.getRange('a1');
  var row = 0;
  while(rs.next()) 
    cell.offset(row, 0).setValue(rs.getString(1));
    cell.offset(row, 1).setValue(rs.getString(2));
    cell.offset(row, 2).setValue(rs.getString(3));
    cell.offset(row, 3).setValue(rs.getString(4));
    cell.offset(row, 4).setValue(rs.getString(5))
    row++;
  
  rs.close();
  stmt.close();
  conn.close();

在此特定查询的示例中,它读取和写入约 1200 行,最初脚本完成大约需要 1.5 分钟,但随后似乎有某种缓存,因为在初始后重新查询只需要大约 30 秒脚本的运行。

这是一个不错的运行时间,但是当我将其与连接到 Excel 中的数据进行比较时,它仍然相当长。

所以我一直在尝试用我有限的知识来看看我是否可以让它更快。

经过一些简短的谷歌搜索后,我发现this 文章表明使用数组来保存数据会更有效。

因此,凭借这些知识和一些额外的谷歌搜索,我发现了这个脚本:

var address = "server"; //ex. '10.1.1.1:1433'
var user = "UN";
var userPwd = "PW";
var db = "DB";

var dbUrl = 'jdbc:sqlserver://' + address + ';databaseName=' + db;   

function UpdatePriceList() 
  var conn = Jdbc.getConnection(dbUrl, user, userPwd); 
  var stmt = conn.createStatement();

  var results = stmt.executeQuery("SELECT * FROM [dbo].[PriceList]WHERE [Product Line]='AL' OR [Product Line]='EL'OR [Product Line]='Accessories'ORDER BY [Product Line],Family,[Item Code]");
  var metaData=results.getMetaData();
  var numCols = metaData.getColumnCount();

  var sheet = SpreadsheetApp.getActive().getSheetByName('Data');
  sheet.clearContents();

  var arr=[];  
  for (var col = 0; col < numCols; col++) 
    arr.push(metaData.getColumnName(col + 1));
     
  sheet.appendRow(arr);

  while (results.next()) 
    arr=[];   
    for (var col = 0; col < numCols; col++)    
      arr.push(results.getString(col + 1));
    
    sheet.appendRow(arr);   
  

  results.close();
  stmt.close();
  conn.close();

  sheet.autoResizeColumns(1, numCols+1);   

令我惊讶的是,使用新脚本执行相同的查询需要 5-7 分钟才能完成,我不知道为什么。似乎也没有像使用其他脚本那样进行任何缓存,因此它始终需要大约相同的时间才能完成,而在使用前者初始运行之后,时间上却有相当大的增益。

我喜欢后者更具动态性,因为我不必根据查询结果调整循环内容,因为我重用了脚本,但是运行时的差异扼杀了这种新颖性。

任何人都可以就如何使后者的动态特性适应前者和/或就如何改进此脚本以实现更快的运行时提供任何建议吗?

【问题讨论】:

考虑使用getRange(..).setValues 而不是appendRow。第一个脚本没有调用原子操作,setValues 也不是原子的。 创建一个值数组,然后在一个操作中将它们插入到一个范围内,比一个接一个地插入许多单行要快。 @ra89fi 谢谢你的回复,我也是这么想的,但是我对如何执行这个概念有点缺乏经验,你能举个例子吗? @aaron ***.com/help/someone-answers 【参考方案1】:

此代码从结果对象中逐一读取一行并附加到工作表中。替换这个 -

  while (results.next()) 
    arr=[];   
    for (var col = 0; col < numCols; col++)    
      arr.push(results.getString(col + 1));
    
    sheet.appendRow(arr);   
  

有了这个-

var rows = [];
while (results.next()) 
    var arr=[];   
    for (var col = 0; col < numCols; col++)    
      arr.push(results.getString(col + 1));
    
    rows.push(arr);


sheet.getRange(2, 1, rows.length, numCols).setValues(rows);

【讨论】:

完美!这就是我一直在寻找的。​​span> 现在在sheet中写入数据需要多长时间? 现在时钟在 ~15-20 秒,我再高兴不过了。再次感谢!

以上是关于如何优化我的 Google 脚本以更快地检索 SQL 数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何优化推理脚本以获得更快的分类器预测?

优化Google脚本值检索

如何优化限制查询以更快地从大表中访问数据?

在 Swift 中,如何在继续编写代码之前安全地确保从 Google 检索数据(日期和时间)?

如果我将我的应用程序部署到 GCP,我能否以某种方式让 google bq 工作得更快

在 Python 中优化 for 循环以更快地工作