情况很简单,oracle中有一个表用作数据交换的"共享表"。表格结构和记录数量保持不变。在正常情况下,我会不断将数据更新到该表中,其他进程会读取该表中的当前数据。
奇怪的是,当我的进程开始时,每个更新语句执行的时间消耗大约为2毫秒。经过一段时间(比如8小时)后,每个语句的时间消耗增加到了10~20毫秒。这使得程序相当缓慢。
表的结构
更新语句如下:
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);
}
}
使用qt接口的更新语句
有很多原因可以导致逆戟鲸行动迟缓,但我找不到任何线索来解释这一点。
我从不在qt代码中手动启动事务,这意味着每次更新语句后都会执行提交操作。
更新频率约为每秒200条记录,但数量会随时间动态变化。它可能在一次内增加到1000,在下一次内下降到10。
一旦每条语句的时间消耗达到10-20ms,它就永远不会停止只有重新启动oracle服务,时间消耗才能恢复到2ms。(关闭或重新启动任何访问orcle的用户进程都是无用的)
请告诉我如何解决它,或者至少要检查什么。
好的起点是检查AWR和ASH报告。
比较"好"one_answers"坏"时期的报告,你可以发现变化的原因。例如,这可能是执行计划的更改或等待事件的增加。一个可能的结果是,您看到的唯一变化是数据库在客户端上等待了更多的时间(即问题不在数据库中)。
无论如何,正如其他答案中所诊断的那样,问题的根本原因似乎是循环中的更新。如果你的更新列表很长(比如说超过10-100个条目),你可以通过使用MERGE在一条语句中更新整个列表来获利。
- 从列表中构建集合
- 将集合强制转换为TABLE
- 在MERGE语句中使用此表可以更新行
请参阅此处了解详细信息。
您可以在会话快速运行时跟踪会话,稍后在会话缓慢运行时再次跟踪会话。使用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
这样既可以更快地执行更新,又只发出一次提交。