连续使用 sql "update" 时,Oracle 意外且快速地减速

Oracle slow down unexpected and rapidly when using sql "update" continuously

情况很简单,oracle中有一个table作为数据交换的"shared table"。 table 结构和记录数保持不变。在正常情况下,我不断将数据更新到此 table 中,其他进程读取此 table 以获取当前数据。

奇怪的是,当我的进程启动时,每条update语句执行的耗时大约是2ms。并且在一定时间后(比如 8 小时),每条语句的耗时增加到 10 ~ 20 ms。它使过程非常缓慢。

the structure of table

更新语句如下:

anaNum = anaList.size(); 
qry.prepare(tr("update YC set MEAVAL=:MEAVAL, QUALITY=:QUALITY, LASTUPDATE=:LASTUPDATE where YCID=:YCID")); 
foreach(STbl_ANA ana, anaList) 
{ 
   qry.bindValue(":MEAVAL",ana.meaVal); 
   qry.bindValue(":QUALITY",ana.quality); 
   qry.bindValue(":LASTUPDATE",QDateTime::fromTime_t(ana.lastUpdate)); 
   qry.bindValue(":YCID",ana.ycId); 
   if(!qry.exec()) 
   { 
     qWarning() << QObject::tr("update yc failed, ") 
        << qry.lastError().databaseText() << qry.lastError().driverText(); 
     failedAnaList.append(ana); 
   } 
}

the update statement using qt interface

导致 orcle 运行变慢的原因有很多,但我找不到解释的线索。

  1. 我在qt代码中从来不手动启动事务,也就是说每次更新语句后都会执行commit操作

  2. 更新频率约为每秒200条记录,但数量是随时间动态变化的。可能上一次增加到1000,下一次又降到10。

  3. 一旦每条语句的耗时达到10~20ms,就再也不会下降了。 只有重启oracle服务才能恢复到2ms耗时。(关闭或重启任何访问orcle的用户进程都没有用)

请告诉我如何解决或至少要检查什么。

您可以在 运行 时快速跟踪会话,然后在 运行 时缓慢跟踪会话。使用 sql 跟踪功能和 tkprof 来详细了解更新在每种情况下花费的时间,并查看发生了什么变化。

https://docs.oracle.com/cd/E25178_01/server.1111/e16638/sqltrace.htm#i4640

如果您需要帮助解释结果,您可以更新您的问题或提出新问题。

其次,通常单个记录更新不是在 Oracle 中进行更新的最佳方式。由于在准备查询之前您已经准备好许多要更新的记录,请查看 execBatch。

https://doc.qt.io/qt-4.8/qsqlquery.html#execBatch

这将更快地执行更新并且只发出一次提交。

最好的起点是查看 AWR and ASH 报告。

比较 "good" 和 "bad" 次的报告,您可以发现变化的原因。例如,这可以是 执行计划的更改或等待事件的增加 。一种可能的结果是,您看到的唯一变化是 数据库在客户端 上等待更多时间(即问题不在数据库中)。

无论如何,正如其他答案所诊断的那样,问题的根本原因似乎是循环更新。如果您的更新列表很长(比如超过 10-100 个条目),您可以通过使用 MERGE 在单个语句中更新整个列表来获益。

  • 从您的列表中创建一个集合
  • 将集合转换为 TABLE
  • 在 MERGE 语句中使用此 table 更新行。

有关详细信息,请参阅 here