2009-05-12 38 views
7

Tôi cần tải lên tệp CSV lớn (16GB, 65+ triệu bản ghi) vào một bảng trong cơ sở dữ liệu SQL Server 2005. Có ai có bất kỳ con trỏ trên cách tốt nhất để làm điều này?Tải tệp CSV lớn lên cơ sở dữ liệu SQL Server

Chi tiết

Tôi hiện đang sử dụng một C# giao diện điều khiển ứng dụng (.NET framework 2.0) để phân chia các tập tin nhập khẩu vào các tập tin của 50000 hồ sơ, sau đó xử lý mỗi file. Tôi tải lên các bản ghi vào cơ sở dữ liệu từ ứng dụng giao diện điều khiển bằng cách sử dụng lớp SqlBulkCopy theo lô 5000. Để tách các tệp mất khoảng 30 phút và tải lên toàn bộ tập dữ liệu (65+ triệu bản) mất khoảng 4,5 giờ. Kích thước tệp được tạo và kích thước tải lên hàng loạt đều là cài đặt cấu hình và tôi đang điều tra tăng giá trị của cả hai để cải thiện hiệu suất. Để chạy ứng dụng, chúng tôi sử dụng một máy chủ lõi tứ với RAM 16 GB. Máy chủ này cũng là máy chủ cơ sở dữ liệu.

Cập nhật

Với câu trả lời cho đến nay, xin lưu ý rằng trước khi nhập khẩu:

  • Bảng cơ sở dữ liệu là cắt ngắn, và tất cả các chỉ số và hạn chế được giảm xuống.
  • Cơ sở dữ liệu bị thu hẹp và không gian đĩa được khôi phục.

Sau khi đã nhập xong:

  • Các chỉ số được tái

Nếu bạn có thể đề nghị bất kỳ phương pháp khác nhau, hoặc cách chúng tôi có thể cải thiện các ứng dụng nhập khẩu hiện có, tôi sẽ đánh giá cao nó . Cảm ơn.

Câu hỏi liên quan

Câu hỏi sau đây có thể được sử dụng cho những người khác đối phó với vấn đề này:

Giải pháp

tôi đã điều tra các ảnh hưởng của việc thay đổi kích cỡ lô, và kích thước của các tệp phân tách, và thấy rằng các lô của 500 bản ghi và chia nhỏ 200.000 bản ghi hoạt động tốt nhất cho ứng dụng của tôi. Việc sử dụng số SqlBulkCopyOptions.TableLock cũng đã giúp ích. Xem câu trả lời cho số này question để biết thêm chi tiết.

Tôi cũng đã xem xét sử dụng gói SSIS DTS và tập lệnh SQL BULK INSERT. Gói SSIS xuất hiện nhanh hơn, nhưng không cung cấp cho tôi khả năng ghi lại các bản ghi không hợp lệ, vv Tập lệnh SQL BULK INSERT trong khi chậm hơn gói SSIS, nhanh hơn đáng kể so với ứng dụng C#. Nó đã cho phép tôi ghi lại các lỗi, vv, và vì lý do này, tôi chấp nhận câu trả lời BULK INSERT từ ConcernedOfTunbridgeWells làm giải pháp. Tôi biết rằng đây có thể không phải là câu trả lời hay nhất cho mọi người đối mặt với vấn đề này, nhưng nó giải đáp được vấn đề trước mắt của tôi.

Nhờ mọi người đã trả lời.

Kính trọng, MagicAndi

Trả lời

5

BULK INSERT được chạy từ chính DBMS, đọc tệp được mô tả bằng tệp kiểm soát bcp từ thư mục trên máy chủ (hoặc được gắn trên đó). Viết một ứng dụng chia nhỏ tệp thành các phần nhỏ hơn, đặt chúng vào một thư mục thích hợp thực hiện một trình bao bọc thực thi một loạt các BULK INSERTS. Bạn có thể chạy nhiều luồng song song nếu cần.

Đây có thể là nhanh như tải hàng loạt. Ngoài ra, nếu có một khóa phân vùng thích hợp có sẵn trong tệp tải số lượng lớn, hãy đặt bảng dàn dựng trên lược đồ phân vùng.

Ngoài ra, nếu bạn đang tải hàng loạt vào một bảng có chỉ số nhóm, hãy đảm bảo dữ liệu được sắp xếp theo thứ tự giống như chỉ mục. Hợp nhất sắp xếp là bạn của bạn cho các tập dữ liệu lớn.

+0

Đó là những gì lớp SqlBulkCopy làm. –

+0

Không hoàn toàn đúng. SqlBulkCopy kết thúc tốt đẹp API tải hàng loạt OLEDB mà vẫn đang đẩy dữ liệu qua liên kết máy khách-máy chủ. BULK INSERT chạy trong quá trình trên máy chủ. – ConcernedOfTunbridgeWells

+0

ConcernedOfTurnbridgeWells, Cảm ơn câu trả lời +1. Tôi kiểm tra giải pháp của bạn và để lại một số phản hồi càng sớm càng tốt. – MagicAndi

2

Lớp SqlBulkCopy mà bạn đã sử dụng sẽ là lựa chọn tốt nhất của bạn. Điều tốt nhất bạn có thể làm từ đây trong mã C# của bạn là thử nghiệm với hệ thống và dữ liệu cụ thể của bạn để xem kích thước lô nào hoạt động tốt nhất. Nhưng bạn đã làm điều đó.

Vượt mã khách hàng, có thể có một số điều bạn có thể làm với các máy chủ để làm cho thời gian nhập khẩu hiệu quả hơn:

  • Hãy thử thiết lập bảng và cơ sở dữ liệu kích thước trước khi bắt đầu nhập một cái gì đó lớn đủ để giữ toàn bộ thiết lập. Bạn không muốn dựa vào tự động phát triển ở giữa điều này.

  • Tùy thuộc vào cách dữ liệu được sắp xếp và bất kỳ chỉ mục nào trong bảng, bạn có thể làm tốt hơn một chút để giảm bất kỳ chỉ mục nào không khớp với thứ tự mà các bản ghi được nhập và sau đó tạo lại chúng sau nhập.

  • Cuối cùng, bạn nên thử chạy song song, với một vài chuỗi chèn hàng loạt cùng một lúc. Tuy nhiên, nút cổ chai lớn nhất là gần như chắc chắn hiệu suất đĩa. Bất cứ điều gì bạn có thể làm cho máy chủ vật lý để cải thiện điều đó (đĩa mới, san, v.v.) sẽ giúp ích nhiều hơn.

+0

Joel, Cảm ơn câu trả lời của bạn. Xem câu hỏi được cập nhật để biết một số thông tin mới, trả lời một số điểm từ câu trả lời của bạn. Tuy nhiên, tôi đã có một chút ngạc nhiên khi thấy rằng bạn đề nghị sử dụng các chủ đề pararllel. Các luồng sẽ được tải lên trên cùng một bảng cơ sở dữ liệu trên máy chủ. Sẽ không hoạt động tải lên hàng loạt từ một chủ đề khóa bảng và dẫn đến các chủ đề khác đang chờ nó phát hành bảng? – MagicAndi

+0

Tôi không có ý thực sự đề xuất các chủ đề song song. Tôi đã cố gắng để nói rằng nó sẽ được hấp dẫn, nhưng không có khả năng thực sự giúp bạn có được bất cứ nơi nào vì hiệu suất đĩa là quan trọng hơn. –

+0

Cảm ơn bạn đã làm rõ. +1. – MagicAndi

0

Gần đây, tôi cũng phải tải lên/nhập nhiều nội dung (xây dựng một tập lệnh PHP).

Tôi đã quyết định xử lý hồ sơ để ghi.

Tất nhiên, nó mất nhiều thời gian, nhưng đối với tôi, những điểm sau đây là quan trọng: - dễ dàng tạm dừng quá trình - gỡ rối tốt hơn

Đây chỉ là một mẹo.

regards, Benedikt

+0

Benedikt, sử dụng ứng dụng C#, tôi vẫn đang xử lý từng bản ghi trong khi đọc các tệp đã tạo. Điều này cho phép tôi xác thực từng bản ghi, v.v. trước khi thử tải lên, tôi có nên muốn. – MagicAndi

3

Các bạn đã thử SSIS (SQL Server Integration Services).

+0

Chris, Cảm ơn câu trả lời của bạn, tôi sẽ quan tâm đến việc tìm kiếm thêm về việc sử dụng SSIS. Bạn có thể liên kết với các ví dụ về việc sử dụng SSIS để tải lên dữ liệu từ một tệp không? Cảm ơn. – MagicAndi

+0

SSIS có trình đọc CSS gốc (Nguồn Tệp Phẳng). Chỉ cho người đọc vào loại đầu ra chính xác. SSIS cũng được cho là để bó các chèn. Thật không may, việc dạy SSIS là một chủ đề lớn hơn định dạng này cho phép - và SSIS khá là đồ họa trong tự nhiên. –

0

BULK INSERT có lẽ đã là cách nhanh nhất. Bạn có thể đạt được hiệu suất bổ sung bằng cách xóa các chỉ mục và các ràng buộc trong khi chèn và thiết lập lại chúng sau này. Tác động hiệu suất cao nhất đến từ các chỉ mục nhóm.

0

Bạn đã thử Dịch vụ tích hợp SQL Server cho điều này chưa? Có thể tốt hơn khi xử lý một tệp văn bản lớn như vậy

0

Chỉ cần kiểm tra, quá trình chèn của bạn sẽ nhanh hơn nếu không có chỉ mục nào trên bảng bạn đang chèn vào.

+0

Điều này chỉ đúng một phần. Tôi đã thấy nhập hàng loạt mất _longer_ khi thử điều này, vì dữ liệu nhập đã khớp với thứ tự chỉ mục. –

2

Bạn có thể lưu các bước của việc tách các tập tin như sau:

  • Khởi tạo một IDataReader để đọc các giá trị từ tập tin CSV đầu vào. Có một số cách để làm điều này: dễ nhất có lẽ là sử dụng trình điều khiển Microsoft OleDb Jet. Google cho điều này nếu bạn cần thêm thông tin - ví dụ: có một số thông tin trong this StackOverflow question.

    Phương pháp thay thế là sử dụng một kỹ thuật tương tự như được sử dụng bởi www.csvreader.com.

  • Khởi tạo đối tượng SqlBulkCopy, đặt thuộc tính BatchSize và BulkCopyTimeout thành giá trị phù hợp.

  • Chuyển IDataReader sang phương thức SqlBulkCopy.WriteToServer.

Tôi đã sử dụng kỹ thuật này thành công với các tệp lớn, nhưng không lớn bằng kỹ thuật của bạn.

1

Xem thisthis bài đăng trên blog để so sánh. Có vẻ như cách thay thế tốt nhất là sử dụng BulkInsert với tùy chọn TABLOCK được đặt thành true.

+0

Santiiiii, Cảm ơn bạn đã liên kết, được đánh giá cao. +1 – MagicAndi

0

kịch bản của tôi cho những thứ như đó là: Tạo SSIS gói trên SQL server mà sử dụng BLUK chèn vào sql, Tạo thủ tục lưu trữ bên trong cơ sở dữ liệu để có thể chạy mà gói từ mã T-SQL

Sau khi gửi mà tập tin cho bluk chèn vào máy chủ SQL bằng cách sử dụng FTP và gọi SSIS Gói usinfg được lưu trữ thủ tục

Các vấn đề liên quan