是否有更好的方法从结果集中检索结果?对每个值调用
getString()
非常慢。将大约 400 行、16 列放入一个数组中最多需要 2.5 秒才能使用它。
查询本身只需要大约 80 毫秒,比访问 Google Sheet(大约 2 秒)要快,但读取数据需要的时间太长。
我现在用的就是这个。
var results = stmt.executeQuery();
var numCols = results.getMetaData().getColumnCount();
var resultsArray = [];
var count = 0;
while(results.next()) {
resultsArray.push([]);
for (var i = 1; i <= numCols; i++)
resultsArray[count].push(results.getString(i));
count++;
}
setFetchSize()
设置为所需的所有行。
results.setFetchSize(400);//for 400rows
results.setFetchSize(4000);//for 4000rows
修改查询可能有助于加快该过程。例如,对于 MS SQL Server,您可以在末尾添加
FOR JSON
。所以不会有柱子。在 GAS 中接收结果将如下所示:
let conn = Jdbc.getConnection('your connection string');
let statement = conn.createStatement();
let results = statement.executeQuery('your query');
let resultJSON;
while (results.next()) resultJSON += results.getString(1);
let resultObject = JSON.parse(resultJSON);
此处使用 While 循环,因为 JSON 字符串可能会被分割成一定数量的行。
从 V8 开始,读取时间甚至更长,回到 Rhino 可以解决这个问题(暂时)。您只需停用:设置 > 运行 V8
https://issuetracker.google.com/issues/191684323
编辑:
Rhino 不再是一个好主意,并且开始表现得很奇怪,例如日志不显示,API 调用没有答案。
我找到了一个使用Cloud Function的解决方案,它需要访问Cloud SQL,并由Apps Script使用Urlfetch调用。它速度非常快,并且可以确保仅对某些用户可用。
首先,我建议遵循:https://cloud.google.com/sql/docs/mysql/connect-functions
云函数示例(使用 Node.js):
exports.connect= async (req, res) => {
var mysql = require('promise-mysql');
var pool = await mysql.createPool({
socketPath : '/cloudsql/' + PROJECT_ID,
user : USERNAME,
password : PASSWORD,
database : BASE
});
pool.getConnection(function (err, conn) {
if (err) {
return res.status(400).send('bad connexion');
}
conn.query('SELECT * FROM TABLE_EXAMPLE', function(err, rows) {
if (err) {
return res.status(400).send('No connexion');
}
res.status(200).send(rows);
conn.release();
})
});
};
有趣的是,将 console.log(results.getRow()) 添加到 while() 循环内部极大地提高了 results.getString(i) 的速度。也许这也会对你有帮助:
while(results.next()) {
console.log(results.getRow());
resultsArray.push([]);
for (var i = 1; i <= numCols; i++)
resultsArray[count].push(results.getString(i));
count++;
}
希望这可以帮助其他遇到同样问题的人!