json - Grails 批量更新 postgres 性能

标签 json performance postgresql grails

我正在尝试使用 Grails 和 json 对 postgres 数据库进行一次大的事务更新。我有一个压缩的 json 文件,我正在从中读取属性并相应地更新数据库。

好吧,我正在从文件中读取 json

new FileInputStream("/home/export.gz")

将其传递给解压缩流并创建 json 解析器
GZIPInputStream gzipInputStream = new GZIPInputStream(is)
JsonParser jp = new JsonFactory().createParser(gzipInputStream);

解析 json 字段...
    while (jp.nextToken() != null) {
        if (jp.getCurrentToken() == JsonToken.START_OBJECT) {
            if (jp.nextToken() == JsonToken.FIELD_NAME) {
              ...
            }
        } 
    }

像这样从数据库中加载每一行
private <C> C getById(Class<C> clazz, def id) {
    Criteria criteria = sessionFactory.getCurrentSession().createCriteria(clazz).setCacheMode(CacheMode.IGNORE)
    criteria.add(Restrictions.idEq(id))
    return (C) criteria.uniqueResult()
}

得到行,设置字段,刷新每一行
private void flushAndEvict(def o) {
    sessionFactory.getCurrentSession().flush()
    sessionFactory.getCurrentSession().evict(o)
    o.discard()
}

问题是这种方法随着时间的推移变得越来越慢。
它从更新 500 行/秒开始,大约 4000 更新速度为 100 行/秒,到更新 30 000 行时,速度为 10 行/秒,50 000 更新大约为 5 行/秒。

监控性能我发现内存一切正常,gc 峰值不会超过 5% 的 cpu 时间。

CPU 正在全功率运行,100%,50%(挂墙时间) sleep ,42% SocketInputStream.read(byte[], int, int)。

我看到更多的是套接字读/写速度变慢,从 session 结束时的 10 kb/s、5kb/s 开始。

我试图了解这里的瓶颈以及如何提高性能。什么会导致这种速度下降?

最佳答案

我建议你每 500 或 1000 次刷新一次(你应该检查你的时间并选择一个),然后你应该清除你的 session 。这样您就不会再有任何延迟,您的时间将变得线性。

def BATCH_SIZE = 1000 // or 500

def myListOfJsonsParsed = [] //...

// ...
def count = 0
myListOfJsonsParsed.each {
    def o = getById(..., it.id)
    // update o fields
    o.save()
    count++
    if(count >= BATCH_SIZE) {
        count = 0
        flushAndClear()
    }
}
flushAndClear()
// ...

private void flushAndClear() {
    sessionFactory.getCurrentSession().flush()
    sessionFactory.getCurrentSession().clear()
}

private <C> C getById(Class<C> clazz, def id) {
    Criteria criteria = sessionFactory.getCurrentSession().createCriteria(clazz).setCacheMode(CacheMode.IGNORE)
    criteria.add(Restrictions.idEq(id))
    return (C) criteria.uniqueResult()
}

这不会是一个大事务,这将更新每个 BATCH_SIZE 元素,如果你的 json 真的很大,这就是这样做的方法。另一方面,如果您想进行大量交易,则根本不应该使用刷新。
@Transactional
public void updateDatabase(def myListOfJsonsParsed) {
    myListOfJsonsParsed.each {
        def o = getById(..., it.id)
        o.save()
    }
}

但如果 ,我不会推荐它。 myListOfJsonsParsed 有很多元素。

关于json - Grails 批量更新 postgres 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31802623/

相关文章:

sql - 使用 PostgreSQL ECPG 插入数组

javascript - JSON - 对象中的数组中的对象 - 如何使用 JS 解析循环?

javascript - 如何在html中使用javascript重复解析json数据

java - 初始化默认 SSL 上下文失败

performance - 序言程序: clp(fd) too slow无输出

c# - 我怎样才能在 C# stream.Read 到非托管内存流?

sql - 'having' 子句后的 'group by ' 错误

java - Jackson动态Pojo<T>反序列化

c++ - 解释需要 : log10 faster than log and log2, 但仅限于 O2 和更大

sql - 如何从 PostgreSQL 的时间范围内选择日期?