Cập nhật / chèn cơ sở dữ liệu hàng loạt từ tệp CSV


8

Tôi đang thực hiện tính năng nhập dữ liệu cụ thể của ứng dụng từ cơ sở dữ liệu này sang cơ sở dữ liệu khác.

Tôi có một tệp CSV chứa 10000 hàng. Những hàng này cần được chèn / cập nhật vào cơ sở dữ liệu.

Có thể có trường hợp, trong đó một vài hàng có thể xuất hiện trong cơ sở dữ liệu có nghĩa là những hàng cần được cập nhật. Nếu không có trong cơ sở dữ liệu, những người cần phải được chèn.

Một giải pháp khả thi là, tôi có thể đọc từng dòng một, kiểm tra mục nhập trong cơ sở dữ liệu và xây dựng các truy vấn chèn / cập nhật tương ứng. Nhưng quá trình này có thể mất nhiều thời gian để tạo các truy vấn cập nhật / chèn và thực hiện chúng trong cơ sở dữ liệu. Đôi khi tệp CSV của tôi có thể có hàng triệu bản ghi.

Có cách nào khác nhanh hơn để đạt được tính năng này?

java  oracle 

Cố gắng xử lý nó theo từng phần hoặc nếu không, việc đọc CSV lớn trong một lần chụp sẽ cho kết quả OutOfMemory!

@TheNewIdiot sẽ không xảy ra nếu sử dụng đủ bộ nhớ như một máy chủ đàng hoàng, tiêu tốn ít nhất 2 GB ram cho JVM. Nó cũng sẽ phụ thuộc vào loại dữ liệu trong tệp CSV và nếu quy trình sẽ chạy trong một quy trình duy nhất hoặc bên cạnh quy trình khác được xử lý trong máy chủ.

@Luiggi Mendoza: Tôi đồng ý với bạn. Chúng tôi có đủ bộ nhớ để xử lý tệp CSV lớn trong sản xuất.

Câu trả lời:


7

Có một công nghệ tốt có sẵn trong Oracle gọi là Bảng ngoài. Trong kịch bản của bạn, bạn có thể truy cập dữ liệu văn bản đơn giản bên ngoài bằng Bảng bên ngoài từ bên trong cơ sở dữ liệu và cập nhật dữ liệu hiện có trong cơ sở dữ liệu bằng các câu lệnh SQL mà bạn yêu thích và được sử dụng - ví dụ INSERT, MERGEv.v.

Trong hầu hết các trường hợp, sử dụng các tiện ích do Oracle cung cấp là cách tốt nhất để thực hiện ETL. Và bởi vì câu hỏi của bạn nghe giống câu hỏi hành chính hơn, tôi khuyên bạn nên xem bài viết trước của tôi trên DBA Stack Exchange "Cập nhật cơ sở dữ liệu Oracle từ CSV" .

CẬP NHẬT: Cách tiếp cận này hoạt động khá tốt để đọc dữ liệu ngoài trong cơ sở dữ liệu. Nói chung, bạn xác định định dạng dữ liệu ngoài mỗi lần bạn cần xử lý tệp văn bản thuần có định dạng mới. Khi bảng bên ngoài được tạo, bạn có thể truy vấn nó giống như bảng cơ sở dữ liệu thực. Bất cứ khi nào có dữ liệu mới để nhập, bạn chỉ cần thay thế (các) tệp bên dưới một cách nhanh chóng mà không cần phải tạo lại (các) bảng bên ngoài. Vì bảng bên ngoài có thể được truy vấn như bất kỳ bảng cơ sở dữ liệu nào khác, bạn có thể viết các câu lệnh SQL để điền vào các bảng cơ sở dữ liệu khác.

Chi phí sử dụng Bảng ngoài thường thấp hơn so với các kỹ thuật khác mà bạn sẽ triển khai thủ công vì công nghệ này được thiết kế với hiệu suất trong tâm trí có tính đến kiến ​​trúc Cơ sở dữ liệu Oracle.


Tôi đồng ý đây là một trong những giải pháp để đạt được mục tiêu của mình. Cách tiếp cận này có thể phù hợp để xử lý CSV động? Có nghĩa là, người dùng ứng dụng của tôi có cơ hội tải lên nhiều tệp với các định dạng khác nhau (trong trường hợp này cần phải tạo các câu chuyện bên ngoài một cách nhanh chóng). Ngoài ra, một tệp CSV có thể chứa dữ liệu cần được điền vào nhiều bảng.

1

Tôi nghĩ bạn nên sử dụng SQL * Loader để tải tệp CSV vào bảng tạm thời và sau đó sử dụng câu lệnh MERGE để chèn dữ liệu vào bảng làm việc.
SQL * Loader sẽ cung cấp cho bạn sự linh hoạt hơn sau đó các bảng bên ngoài và nếu một người sử dụng tải đường dẫn trực tiếp thì nó thực sự nhanh. Và MERGE sẽ làm chính xác những gì bạn cần - XÁC NHẬN hồ sơ mới và CẬP NHẬT những hồ sơ hiện có.
Một vài liên kết để bắt đầu:
http://docs.oracle.com/cd/B19306_01/server.102/b14215/ldr_con
accept.htmlm http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016 .htm


1
Khi bạn tải dữ liệu vào cơ sở dữ liệu bằng SQL Loader, quy trình DBWR hoặc SQL Loader ghi bộ đệm vào các tệp dữ liệu. Khi bạn sau đó di chuyển dữ liệu được tải sang các bảng khác, cơ sở dữ liệu sẽ thực hiện một I / O khác. Tôi không nghĩ rằng công việc làm thêm này có thể được biện minh. Nhân tiện, khi Bảng bên ngoài sử dụng trình điều khiển ORACLE_LOADER, cú pháp xác định định dạng dữ liệu đầu vào được sử dụng tương tự bởi tiện ích sqlldr vì về cơ bản chúng là cùng một công nghệ và do đó có thể được sử dụng thay thế cho nhau. Các bảng bên ngoài trong kịch bản này được ưa thích vì trước tiên không cần tải dữ liệu vào cơ sở dữ liệu
Yasir Arsanukaev 17/07/13

Như câu trả lời thông thường là "nó phụ thuộc" :). Trong trường hợp của chúng tôi, việc tải vào bảng tạm thời sẽ thuận tiện hơn và xử lý sau. Vì tải đường dẫn trực tiếp không tạo ra làm lại nên I / O bổ sung gần như không được chú ý trong số các hoạt động khác. Trong các trường hợp khác tất nhiên các phương pháp khác sẽ tốt hơn.
Mindaugas Riauba

0

PreparedStatements sẽ làm cho việc tạo các truy vấn chèn hoặc cập nhật rất nhanh. Bạn nên có ba PreparedStatements: Một để chèn, một để cập nhật và một để kiểm tra xem hàng đã có trong bảng chưa. Nếu bạn có thể giữ ID giống nhau giữa tệp CSV và cơ sở dữ liệu mới, thì việc kiểm tra xem liệu một hàng có xuất hiện bằng trường chínhID hay không cũng sẽ rất nhanh.

Sử dụng một loạt chèn có thể cung cấp một hiệu suất đạt được. Khi bạn truyền phát qua tệp CSV, sau đó bạn sẽ kiểm tra xem hàng đã ở đó chưa và sau đó thực hiện cập nhật hoặc thêm hàng vào lệnh chèn hàng loạt của bạn. Bạn nên kiểm tra câu hỏi SO này để so sánh tốc độ của hai phương pháp này.

Nếu việc nhập cơ sở dữ liệu này là việc cần được thực hiện thường xuyên và hiệu suất là một vấn đề khi sử dụng phương pháp tôi đã nêu ở trên, thì bạn có thể thử xử lý tác vụ với nhiều luồng công nhân. Sử dụng nhiều luồng như chúng là bộ xử lý trên máy chạy mã này.

  int nThreads = Runtime.getRuntime().availableProcessors();

Mỗi luồng có kết nối DB riêng và khi mã của bạn lặp qua tệp, các dòng CSV có thể được chuyển sang các luồng khác nhau. Điều này phức tạp hơn nhiều, vì vậy tôi sẽ chỉ làm điều này nếu các yêu cầu về hiệu suất buộc tôi phải làm.


Cảm ơn vì đã trả lời. Một lần nữa, điều này sẽ yêu cầu phân tích tệp CSV và điền các giá trị vào các câu lệnh đã chuẩn bị. Với phương pháp 'Bảng bên ngoài', tôi thấy phân tích tệp có thể được chuyển sang phía Cơ sở dữ liệu nơi ứng dụng không cần phải quan tâm đến nó. Ngoài ra, tôi đang sử dụng JPA với Hibernate trong ứng dụng của mình. Tôi đang tìm kiếm tùy chọn có thể là sự kết hợp của JPA / Hibernate / Oracle, điều này tạo điều kiện cho việc không phân tích cú pháp tệp, hiệu suất tốt, có thể bảo trì và linh hoạt.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.