在包含数十亿条记录的表上执行查询

时间:2014-07-29 05:47:34

标签: java jdbc

我想从数据库中获取一些记录(可以是50,100或其他由用户配置的)而不使用limit子句,因为我们的应用程序可能在多个数据库上工作,如mysql,oracle,mssql,db2 ....

我做了以下解决方案

package com.test;

import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.util.Date;

public class BatchRetrieveTest extends Object {
    private static final int FETCH_SIZE = 10;

    public BatchRetrieveTest() {
    }

    public static void main(String[] args) {
        BatchRetrieveTest batchRetrieveTest = new BatchRetrieveTest();
        batchRetrieveTest.test();
    }

    void test() {
        Connection conn = null;
        Statement stmt2 = null;
        Date start = null;
        Date end = null;
        int i = 0;
        try {
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/test",
                    "root", "root");
            stmt2 = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                    ResultSet.CONCUR_READ_ONLY);
            conn.setAutoCommit(false);
            stmt2.setFetchSize(FETCH_SIZE);
            stmt2.setPoolable(true);
            start = new Date();
            System.out.println(new Date() + "second execute start"
                    + new Date().getTime());
            ResultSet rs2 = stmt2
                    .executeQuery("SELECT * FROM sample_final_attendance limit 1000");

            end = new Date();
            System.out.println(new Date() + "*************second execute end"
                    + (end.getTime() - start.getTime()));
            rs2.absolute(200000);
            i = 0;
            while (rs2.next()) {
                if (i++ > 100) {
                    break;
                }
            }
            rs2.close();
            stmt2.close();
            end = new Date();
            System.out.println(new Date() + "second read end"
                    + (end.getTime() - start.getTime()));
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                stmt2.close();
                conn.close();
            } catch (Exception e) {
            }
        }
    }
}

此处 sample_final_attendance 表包含15列和3.2百万条记录 执行此程序时,它需要2GB的内存和47秒的执行时间

这里我想知道如果某个表有数十亿的记录,那么它就无法执行

我也建议使用setFetchSize,但问题是相同的

请提出一些解决方案

提前致谢

2 个答案:

答案 0 :(得分:0)

ASFAIK&据了解,该问题与多语言存储中的数据处理更相关。如果您认为,您需要在与数据库类型相互依赖的所有情况下解决相同的问题 - 一种常见的方法是构建服务层。

服务层可以是缓存库,也可以是您创建的地图地图。不要尝试一次查询包含大量记录的数据库,而是将数据作为批处理,并将其存储为pojos池。根据用户的要求,您可以从服务层提供数据。

您可以使用memcache或hazlecast或许多其他缓存库,它们可以直接与数据库集成。我真的不知道你的情况有多复杂。我所做的是一个建议。这构成了一个数据网格,可以使用后台任何数据库中的数据进行填充。

答案 1 :(得分:0)

我们在Statement Object中设置了setMaxRow(int numOfRow),这将限制Statement对象生成的行数,并忽略剩余的行。

看看文档。