sql - Grails过滤器统计信息插入效果

标签 sql performance grails groovy before-filter

我在grails中有一个过滤器,用于捕获所有 Controller 请求,并使用controllerName,actionName,userId,date和guid在数据库中插入一行。效果很好,但是我想找到一种提高性能的方法。现在,大约70到80毫秒的时间来创建一条语句需要花费大约100毫秒的时间。我已经使用了域对象插入,常规Sql和原始Java连接/语句。有没有更快的方法来提高在过滤器中插入单个记录的性能?或者,是否有其他可用于插入的图案?代码(使用常规SQL)如下:

class StatsFilters {

def grailsApplication
def dataSource
def filters =
{
    logStats(controller:'*', action:'*')
    {
        before = {
            if(controllerName == null || actionName == null)
            {
                return true
            }
            def logValue = grailsApplication.config.statsLogging
            if(logValue.equalsIgnoreCase("on") && session?.user?.uid != null & session?.user?.uid != "")
            {
                try{

                    def start = System.currentTimeMillis()
                    Sql sql = new Sql(dataSource)
                    def userId = session.user.uid
                    final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-","");
                    String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')"
                    sql.execute(insert)
                    sql.close()
                    def end = System.currentTimeMillis()
                    def total = end - start
                    println("total " + total)
                }
                catch(e)
                {
                    log.error("Stats failed to save with exception " + e.getStackTrace())
                    return true
                }
            }
            return true
        }
    }
}

}

而我当前的数据源
dataSource {

pooled = true
dialect="org.hibernate.dialect.OracleDialect"
properties {
    maxActive = 50
    maxIdle = 10
    initialSize = 10
    minEvictableIdleTimeMillis = 1800000
    timeBetweenEvictionRunsMillis = 1800000
    maxWait = 10000
    validationQuery = "select * from resource_check"
    testWhileIdle = true
    numTestsPerEvictionRun = 3
    testOnBorrow = true
    testOnReturn = true
}
//loggingSql = true

}

- - - - - - - - - - - 解 - - - - - - - - - - - - -

解决方案是仅生成一个线程并保存统计信息。这样,用户响应时间不会受到影响,但是保存几乎是实时完成的。此应用程序中的用户数量(公司内部,有限的用户组)没有任何更强大的功能。
void saveStatData(def controllerName, def actionName, def userId)
{
    Thread.start{
        Sql sql = new Sql(dataSource)
        final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-","");
        String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')"
        sql.execute(insert)
        sql.close()
    }
}

最佳答案

更好的模式是不将行插入过滤器,而只是将记录添加到某个列表中,然后通过异步作业定期将列表刷新到数据库中(例如,使用Quartz插件)。

如果应用程序崩溃,您可能会丢失一些数据,但是如果您安排该作业频繁运行(例如每隔x分钟),那应该不是问题。

关于sql - Grails过滤器统计信息插入效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20569094/

相关文章:

php - MYSQL: Order Topics By Latest Comment(评论有主题)

SQL Server Management Studio - UNPIVOT 查询 n 列,n 行

sql - Oracle SQL 如何对静态数据集执行集合操作?

java - 基于时间的资源可用性

performance - Numpy 版本的滚动 MAD(平均绝对偏差)

grails - 如何使用log4j(Config.groovy)在控制台中将println输出从控制台重定向到指定的日志文件

grails - 从 S3 将 MP4 视频文件从 Grails Controller 流式传输到 video.js 播放器

mysql - 在 MySQL JOIN 结果中像主键一样组合

c# - LINQ 语句是否比 'foreach' 循环更快?

grails - Grails-如何禁用数据库连接以运行脚本