代码之家  ›  专栏  ›  技术社区  ›  robert trudel

从数据库读取速度非常慢

  •  1
  • robert trudel  · 技术社区  · 5 年前

    我使用spring boot和spring data jpa、hibernate和oracle。

    实际上,我的表中有大约1000万条记录,我需要做一些操作,将信息写入文件,然后删除记录。

    这是一个基本的sql查询

    select * from zzz where  status = 2;
    

    我做了一个测试,没有做任何操作,删除了记录

        long start = System.nanoTime();
        int page = 0;
        Pageable pageable = PageRequest.of(page, LIMIT);
    
        Page<Billing> pageBilling = billingRepository.findAllByStatus(pageable);
    
        while (true) {
            for (Billing: pageBilling .getContent()) {
                //process
                //write to file
                //delete element
            }
    
            if (!pageBilling .hasNext()) {
                break;
            }
    
            pageable = pageBilling .nextPageable();
            pageBilling = billingRepository.findAllByStatus(pageable);
    
        }
        long end = System.nanoTime();
        long microseconds = (end - start) / 1000;
        System.out.println(microseconds + " to write");
    

    结果很糟糕,限制为10000,耗时157分钟,100000 28分钟,数百万19分钟。

    是否有更好的解决方案来提高性能?

    0 回复  |  直到 5 年前
        1
  •  0
  •   Jens Schauder    5 年前

    以下内容可能会显著提高性能:

    1. 你不应该重复第一页。相反,删除已处理的数据并再次选择第一页。实际上,你不需要一个页面,因为你可以在方法名称中编码限制。选择延迟页面的效率相当低。

    2. 加载、处理和删除一批项目的过程应在单独的事务中进行。否则 EntityManager 将保存所有加载的实体,这将使事情变得非常缓慢。

    如果这还不够,你可以看看以下内容:

    1. 检查执行的SQL。这看起来合理吗?如果不考虑切换到 JdbcTemplate NamedParameterJdbcTemplate 用一个 query 采用某种方法 RowCallbackHandler 您应该能够使用单个select语句加载和处理所有行,并在最后处理一个delete语句以删除所有行。这要求您用于过滤的状态在此期间不会改变。

    2. 执行计划是什么样子的?如果他们似乎要检查你的指数。