2010-09-08 11 views
5

Tôi có một bảng với 252759 bộ dữ liệu. Tôi muốn sử dụng DataSet đối tượng để làm cho cuộc sống của tôi dễ dàng hơn, tuy nhiên khi tôi cố gắng tạo một DataSet cho bảng của tôi, sau 3 giây, tôi nhận được java.lang.OutOfMemory.Tập dữ liệu Groovy sql gây ra java.lang.OutOfMemory

Tôi không có kinh nghiệm về Tập dữ liệu, có hướng dẫn nào về cách sử dụng đối tượng Số liệu cho các bảng lớn không?

Trả lời

1

Tại sao không bắt đầu với việc cung cấp bộ nhớ JVM nhiều hơn?

java -Xms<initial heap size> -Xmx<maximum heap size> 

252759 bộ dữ liệu không giống như bất kỳ điều gì làm việc với RAM 4GB + một số bộ nhớ ảo không thể xử lý trong bộ nhớ.

+0

Có thể làm cho dữ liệu thu thập dữ liệu trở nên lười biếng không? Bởi vì bộ nhớ tăng không quy mô rất tốt. – Skarab

+0

Nếu bạn muốn làm điều đó, bạn phải sử dụng JDBC bình thường. Cách thức Groovy thực hiện nó, tức là sao chép toàn bộ tập kết quả vào một mảng, không phù hợp để lấy ra, vì Groovy không bao giờ biết khi nào nó được lưu để đóng kết quả cơ bản, vì không có phương thức close() rõ ràng nào trong danh sách ; do đó, nó sẽ phải để nó mở cho đến khi thu gom rác (có thể không xảy ra bất cứ lúc nào sớm), do đó hút tài nguyên trên máy chủ cơ sở dữ liệu. –

+0

Cảm ơn bạn, tôi thấy rằng tôi không hiểu DataSet API. Trong trường hợp của tôi, các bản ghi trong bảng chứa dữ liệu văn bản và 4GB là không đủ, vì vậy tôi sẽ chuyển về JDBC. Nếu tôi có thời gian, tôi cũng dự định xem GORM (Groovy ORM) là một phần của Grails. – Skarab

7

Bạn có thực sự cần truy xuất tất cả các hàng cùng một lúc không? Nếu không, sau đó bạn chỉ có thể lấy chúng theo lô (ví dụ) 10000 bằng cách sử dụng cách tiếp cận hiển thị dưới đây.

def db = [url:'jdbc:hsqldb:mem:testDB', user:'sa', password:'', driver:'org.hsqldb.jdbcDriver'] 

def sql = Sql.newInstance(db.url, db.user, db.password, db.driver) 
String query = "SELECT * FROM my_table WHERE id > ? ORDER BY id limit 10000" 

Integer maxId = 0 

// Closure that executes the query and returns true if some rows were processed 
Closure executeQuery = { 

    def oldMaxId = maxId 
    sql.eachRow(query, [maxId]) { row -> 

     // Code to process each row goes here..... 
     maxId = row.id 
    } 
    return maxId != oldMaxId 
} 


while (executeQuery()); 

AFAIK limit là một tính năng đặc trưng cho MySQL, nhưng hầu hết các RDBMS khác có tính năng tương đương giới hạn số hàng được truy vấn trả về.

Ngoài ra, tôi chưa thử nghiệm (hoặc thậm chí biên dịch) mã ở trên, vì vậy hãy xử lý cẩn thận!

+0

Tôi muốn sử dụng DataSet để tránh sử dụng sql thô. – Skarab

+0

Nếu bạn muốn thực hiện phương pháp này, bạn phải sử dụng 'Sql'. Có vẻ như không thể sử dụng các tính năng SQL không chuẩn như 'limit' với' DataSet'. –

+0

@Skarab: Thông thường, bạn nên rút nhiều dữ liệu ra khỏi máy chủ cơ sở dữ liệu của mình để thực hiện các thao tác chỉ để tránh sql ... Dữ liệu đó phải được gửi qua dây mạng chậm hơn nhiều so với việc xử lý nó trong máy chủ db. Vì vậy, trong thực tế, bạn đang thêm các vấn đề hiệu suất có thể làm tê liệt ứng dụng của bạn bằng cách làm những việc như thế. – NotMe