【问题标题】:Time Out when Executing a SQL Query. Any Solution?执行 SQL 查询时超时。任何解决方案?
【发布时间】:2021-02-28 00:06:48
【问题描述】:

我们使用 google 脚本将数据从 SQL 数据库获取到电子表格中。该函数有一个时间驱动的触发器。

每次我运行该函数时,都会有一个超时。

异常:查询已超时

当我第二次运行该函数时,它通常可以正常工作。有人对此有解决方案吗?

这里没有显示数据库的地址和密码。

function onOpen() {
var spreadsheet = SpreadsheetApp.getActive();

var menuItems = [
    {name: 'JTL Import', functionName: 'readData'}
];
spreadsheet.addMenu('JTL-Import', menuItems);
}

// Replace the variables in this block with real values.
var address = 'XXXX'; //ex. '10.1.1.1:1433'
var user = 'TAXDOO';
var userPwd = 'XXX';
var db = 'eazybusiness';

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


function StockUnitsSold30days() {
 var conn = Jdbc.getConnection(dbUrl, user, userPwd);


 var stmt = conn.createStatement();

 var results = stmt.executeQuery("SELECT a.cArtNr SKU, aaI18n.cwertvarchar [Cut_ID], CONVERT(FLOAT, ISNULL(wmsLager.fbestand, 0)) [Stock_WMS], CONVERT(FLOAT, ISNULL(StreckenLager.fbestand, 0)) [Stock_Streckenlager], CONVERT(FLOAT, ISNULL(fba.fanzahlfba, 0)) [Stock_FBA], CONVERT(FLOAT, ISNULL(PendingLager.fbestand, 0)) [Stock_Pending], CONVERT(FLOAT, ISNULL(WmsAusgang.Anzahl, 0)) [Units_WMS_Outgoing], CONVERT(FLOAT, ISNULL(fbaAusgang.SumAnzahl, 0)) [Units_FBA_Outgoing],CONVERT(FLOAT, ISNULL(MengeAufWarenEingang.fAnzahlAktuell,0)) [Stock_Wareneingangsplatz] FROM dbo.tartikel a INNER JOIN dbo.tartikelattribut aa ON aa.kartikel = a.kartikel INNER JOIN dbo.tartikelattributsprache aaI18n ON aaI18n.kartikelattribut = aa.kartikelattribut AND aaI18n.ksprache = 0 INNER JOIN dbo.tattributsprache attributI18n ON attributI18n.kattribut = aa.kattribut AND attributI18n.ksprache = 0 AND attributI18n.cname = 'CutDesign_ID' LEFT OUTER JOIN dbo.vlagerbestandfba fba ON a.kArtikel = fba.kartikel LEFT OUTER JOIN dbo.vlagerbestandprolageralle wmsLager ON wmsLAger.kartikel = a.kArtikel AND wmsLager.kwarenlager = 4 LEFT OUTER JOIN dbo.vlagerbestandprolageralle StreckenLager ON StreckenLager.kartikel = a.kArtikel AND Streckenlager.kwarenlager = 5 LEFT OUTER JOIN dbo.vlagerbestandprolageralle PendingLager ON PendingLager.kartikel = a.kArtikel AND PendingLager.kwarenlager = 7 LEFT OUTER JOIN (SELECT a.kArtikel, SUM(wla.fAnzahl) Anzahl FROM   dbo.tBestellung b JOIN dbo.tbestellpos bp ON bp.tBestellung_kBestellung = b.kBestellung JOIN dbo.trechnung r ON r.tBestellung_kBestellung = b.kBestellung JOIN dbo.tLieferschein l ON l.kBestellung = b.kBestellung JOIN dbo.tLieferscheinPos lp ON lp.kBestellPos = bp.kBestellPos JOIN dbo.tWarenLagerAusgang wla ON wla.kLieferscheinPos = lp.kLieferscheinPos JOIN dbo.tArtikel a ON bp.tArtikel_kArtikel = a.kArtikel WHERE  DATEDIFF(dd, b.derstellt, GETDATE()) <= 30 GROUP BY a.kArtikel ) AS WmsAusgang ON WmsAusgang.kArtikel = a.kArtikel LEFT OUTER JOIN (SELECT map.kArtikel, SUM(abp.nQuantityPurchased) SumAnzahl FROM   dbo.pf_amazon_bestellung ab JOIN dbo.pf_amazon_bestellungpos abp ON abp.kAmazonBestellung = ab.kAmazonBestellung JOIN dbo.tBestellung b ON b.cInetBestellNr = ab.cOrderId JOIN dbo.trechnung r ON r.tBestellung_kBestellung = b.kBestellung JOIN dbo.pf_amazon_angebot_mapping map ON map.cSellerSKU = abp.cArtNr WHERE  nFBA = 1 AND cOrderStatus = 'Shipped' AND DATEDIFF(dd, b.derstellt, GETDATE()) <= 30 GROUP BY map.kArtikel) FbaAusgang ON FbaAusgang.kArtikel = a.kArtikel LEFT OUTER JOIN (SELECT DISTINCT ta.kArtikel, twle.fAnzahlAktuell FROM dbo.tArtikel ta JOIN dbo.tWarenLagerEingang twle ON twle.kArtikel = ta.kArtikel JOIN dbo.tWarenlagerPlatz twlp ON twle.kWarenLagerPlatz = twlp.kWarenLagerPlatz WHERE twlp.cName    = 'Wareneingangsplatz') MengeAufWarenEingang ON MengeAufWarenEingang.kArtikel = a.kArtikel");
 var metaData=results.getMetaData();
 var numCols = metaData.getColumnCount();

 var spreadsheet = SpreadsheetApp.getActive();
 var sheet = spreadsheet.getSheetByName("Test");
 //you can use the following line to get the active sheet
 //var sheet = SpreadsheetApp.getActiveSheet();



 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();

sheet.autoResizeColumns(1, numCols+1);


}```

【问题讨论】:

    标签: sql sql-server timeout


    【解决方案1】:

    第一次运行缓慢,之后又快速运行可能表明查询优化不佳。 如果有表扫描,数据可能会在第一次加载到缓存中。第二次在缓存中。

    这是很多 JOINS 和一个大查询。如果可以的话,我会推荐一个存储过程。查询计划可能指示缺少索引。它还应该显示最昂贵的操作。

    如果 30 天是数据的一小部分并且 derstellt 有索引,则直接将该列与日期进行比较。将 DATEDIFF 包裹在列周围会阻止有效使用该列上的索引。

    声明@TodayMinus29DaysMidnight datetime = CAST(GETDATE() - 29 作为日期)

    选择... WHERE b.derstellt

    我还将使用 DISINCT 验证派生表。 GROUP BY 会更好吗?

    【讨论】:

    • 谢谢 - 我会将这些信息传递给我们的数据库专家。我想知道谷歌脚本中是否有一个函数可以重复查询直到它完全执行?
    • 将函数应用于列值会妨碍有效的索引使用。将WHERE 子句谓词DATEDIFF(dd, b.derstellt, GETDATE()) &lt;= 30 重构为WHERE b.derstellt &gt;= DATEADD(dd, -30, GETDATE())
    猜你喜欢
    • 1970-01-01
    • 2011-10-05
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多