Groovy 中的 sql.rows() 运行缓慢

Posted

技术标签:

【中文标题】Groovy 中的 sql.rows() 运行缓慢【英文标题】:sql.rows() in Groovy is running slow 【发布时间】:2016-03-19 20:43:22 【问题描述】:

我正在支持一个 Grails Web 应用程序,它为使用 AmCharts 的客户端显示不同的视觉效果。在其中一个选项卡上,有三个图表,每个图表根据不同的度量从数据库中返回前十名,因此只有十行。完成需要 4-5 甚至更多时间。查询在 10 秒内在数据库上运行。

调用以下服务方法返回结果:

List fetchTopPages(params, Map querySettings, String orderClause) 
    if(!((params['country'] && params['country'].size() > 0) || (params['brand'] && params['brand'].size() > 0) || (params['url'] && params['url'].size() > 0))) 
        throw new RuntimeException('Filters country or brand or url not selected.')
    
    Sql sql = new Sql(dataSource)
    sql.withStatement  stmt -> stmt.fetchSize = 100 
    Map filterParams = acquisitionService.getDateFilters(params, querySettings)
    ParamUtils.addWhereArgs(params, filterParams)
    String query = "This is where the query is"

    ParamUtils.saveQueryInRequest(ParamUtils.prettyPrintQuery(query, filterParams))
    log.debug("engagement pageviews-by-source query: " + ParamUtils.prettyPrintQuery(query, filterParams))
    List rows = sql.rows(query, filterParams)
    rows


经过一番调查,很明显List rows = sql.rows(query, filterParams) 行是占用此加载时间的行。

有没有人遇到过这个问题?为什么 sql.rows() 只返回 10 行的结果,而且查询在 DB 端运行得非常快,却要花这么长时间?

附加信息:

数据库:FSL1D

在 DB 端运行以下命令:java -jar ojdbc5.jar - getversion 返回: “在 Thu_Jul_11_15:41:55_PDT_2013 上使用 JDK5 编译的 Oracle 11.2.0.3.0 JDBC 3.0 默认连接属性资源 2015 年 12 月 16 日星期三 08:18:32 EST"

Groovy 版本:2.3.7 Grails 版本:2.4.41 JDK:1.7.0

【问题讨论】:

要获得更具体的答案,请发布您的数据库、JDBC 驱动程序和 Groovy + JDK 版本 DB: FSL1D 在 DB 端运行以下命令:java -jar ojdbc5.jar - getversion 返回:Oracle 11.2.0.3.0 JDBC 3.0 在 Thu_Jul_11_15:41:55_PDT_2013 上用 JDK5 编译 #Default Connection Properties Resource #Wed Dec 16 08 :18:32 EST 2015 Groovy 版本:2.3.7 Grails 版本:2.4.41 JDK:1.7.0 谢谢,我会尝试设置您的方案。有一个类似的问题here,但没有明确的答案。 非常感谢!是的,我一直在调查这个问题,但正如你所说,没有明确的答案。 【参考方案1】:

我使用驱动程序ojdbc7.jar 设置Groovy Version: 2.3.6 JVM: 1.8.0_11Oracle 12.1.0.2.0

注意在运行之前激活10046 trace 以允许诊断。

import oracle.jdbc.pool.OracleDataSource

def ods = new OracleDataSource();
ods.setURL('url')
ods.setUser('usr')
ods.setPassword('pwd')

def con = ods.getConnection()
def sql = new groovy.sql.Sql(con)
sql.withStatement  stmt -> stmt.fetchSize = 100 
def SQL_QUERY = """select id, col1  from table1 order by id"""
def offset = 150
def maxRows = 20
// activate trace 10046
con.createStatement().execute "alter session set events '10046 trace name context forever, level 12'"

def t = System.currentTimeMillis()
def rows = sql.rows(SQL_QUERY, offset, maxRows)
println "time1 : $System.currentTimeMillis()-t with offset $offset and maxRows $maxRows"

trace 的检查表明该语句被解析并执行,这意味着如果有 ORDER BY 子句,则所有数据都被排序。

正确使用了提取大小,并且只提取了所需的记录 - 这里 170 = 150 + 20。 提取大小为 100 时,这分两步完成(注意 r 参数 - 提取的行数)。

FETCH #627590664:c=0,e=155,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=1169613780,tim=3898349818398
FETCH #627590664:c=0,e=46,p=0,cr=0,cu=0,mis=0,r=70,dep=0,og=1,plh=1169613780,tim=3898349851458

所以基本上我看到的唯一问题是“跳过”的数据通过网络传递到客户端(在那里被忽略)。

这可能会产生非常高的偏移量,并且会产生大量开销(并且比以交互方式运行生成第一页的同一查询花费更多的时间)。

但识别问题的最佳方法很简单,即启用 10046 跟踪并查看发生了什么。我正在使用 level 12 这意味着您还可以获得信息 关于数据库中的等待和绑定变量。

【讨论】:

以上是关于Groovy 中的 sql.rows() 运行缓慢的主要内容,如果未能解决你的问题,请参考以下文章

groovy系列-groovy比起java,有哪些地方写起来更舒服

如何在运行时获取 Grails Config.groovy 中的好东西?

soapui中的groovy脚本怎么写

intellij IDEA为啥运行时不编译grails或groovy了。

从 Access 中的另一个表返回值时,为啥我的查询运行如此缓慢?

select 语句中的函数使我的查询运行非常缓慢