2010-02-16 34 views
33

Tôi đang tìm cách hiệu quả nhất để chèn hàng loạt hàng triệu bộ dữ liệu vào cơ sở dữ liệu. Tôi đang sử dụng Python, PostgreSQL và psycopg2.Psycopg2, Postgresql, Python: Cách nhanh nhất để chèn hàng loạt

Tôi đã tạo danh sách dài các loại hoa tulip cần được chèn vào cơ sở dữ liệu, đôi khi với các công cụ sửa đổi như hình học Simplify.

Cách ngây thơ để làm điều đó sẽ là chuỗi định dạng danh sách INSERT báo cáo, nhưng có ba phương pháp khác mà tôi đã đọc về:

  1. Sử dụng pyformat binding style để chèn tham số
  2. Sử dụng executemany trên danh sách các bộ dữ liệu và
  3. Bằng cách ghi kết quả vào một tệp và sử dụng COPY.

Dường như cách đầu tiên hiệu quả nhất, nhưng tôi sẽ đánh giá cao thông tin chi tiết và đoạn mã của bạn cho tôi biết cách thực hiện đúng.

Trả lời

13

Vâng, tôi sẽ bỏ phiếu cho COPY, cung cấp cho bạn có thể ghi tệp vào máy chủ của ổ cứng (không phải ổ đĩa mà ứng dụng đang chạy) vì COPY sẽ chỉ đọc máy chủ.

+19

Sử dụng con trỏ ps.copg2 của con trỏ.copy_from tệp được khách hàng xử lý. Nó thậm chí không cần phải là một tập tin hệ thống tập tin: bất kỳ đối tượng giống như tập tin python hoạt động tốt. Kiểm tra http://initd.org/psycopg/docs/cursor.html#cursor.copy_from – piro

+1

Trong trường hợp đó, thật thú vị khi xem nó được chèn vào cơ sở dữ liệu như thế nào - Tôi đã được COPYSQL ấn tượng chỉ đọc từ máy chủ hệ thống tệp cục bộ và không có cách nào để sao chép hàng loạt tệp qua sử dụng ứng dụng khách. –

+5

Nó cũng có thể đọc từ 'STDIN', có nghĩa là dữ liệu đến từ ứng dụng khách. Xem tài liệu lệnh sao chép: http://www.postgresql.org/docs/8.4/static/sql-copy.html – piro

1

Người đầu tiên và người thứ hai sẽ được sử dụng cùng nhau, chứ không phải riêng biệt. Thứ ba sẽ là máy chủ hiệu quả nhất mặc dù, vì máy chủ sẽ làm tất cả các công việc khó khăn.

+0

Bạn có thể liên kết với một số mẫu mã không? Tôi không thể tìm thấy bất kỳ tài nguyên psycopg2 nào tốt trên web. –

+0

Psycopg có một hướng dẫn mới: có rất nhiều ví dụ về nó ngay bây giờ. http://initd.org/psycopg/ – piro

+1

Tuyệt vời, cảm ơn. tìm thấy một ví dụ điển hình khác ở đây: http://www.devx.com/opensource/Article/29071/0/page/3, có lẽ là tài nguyên thực hành tốt nhất trên psycopg2. –

10

Có một số psycopg2 manual mới chứa các ví dụ cho tất cả các tùy chọn.

Tùy chọn COPY là hiệu quả nhất. Sau đó, các thực thi. Sau đó, thực hiện với pyformat.

6

Bạn có thể sử dụng a new upsert library:

$ pip install upsert 

(bạn có thể phải pip install decorator đầu tiên)

conn = psycopg2.connect('dbname=mydatabase') 
cur = conn.cursor() 
upsert = Upsert(cur, 'mytable') 
for (selector, setter) in myrecords: 
    upsert.row(selector, setter) 

đâu selector là một đối tượng dict như {'name': 'Chris Smith'}setter là một dict như { 'age': 28, 'state': 'WI' }

Đó là gần như nhanh bằng cách viết mã INSERT tùy chỉnh [/ UPDATE] và chạy trực tiếp bằng psycopg2 ... và nó sẽ không phát sinh nếu hàng đã tồn tại.

+2

Ngày nay, bạn nên sử dụng triển khai thực hiện nội bộ PostgreSQL (yêu cầu phiên bản 9.5+), bao gồm sử dụng 'INSERT [...] ON CONFLICT [...]' https://www.postgresql.org/docs/9.5/ static/sql-insert.html – Rmatt

7

trong kinh nghiệm của tôi executemany không phải là nhanh hơn bất kỳ chạy nhiều chèn mình, cách nhanh nhất là để định dạng một đĩa đơn INSERT với nhiều giá trị bản thân, có lẽ trong tương lai executemany sẽ cải thiện nhưng bây giờ nó là khá chậm

tôi phân lớp một list và quá tải phương pháp append, vì vậy khi một danh sách đạt đến một kích thước nhất định tôi định dạng INSERT để chạy nó

+1

Được thăng hạng: trải nghiệm của bạn được xác minh trong http://stackoverflow.com/questions/8134602/psycopg2-insert-multiple-rows-with-one-query –

+0

Ngoài ra, đó là một mẹo nhỏ gọn với lớp con. –

1

Sau một số thử nghiệm, unnest thường dường như là một lựa chọn cực kỳ nhanh chóng, như tôi đã học được từ @Clodoaldo Neto của answer cho một câu hỏi tương tự.

data = [(1, 100), (2, 200), ...] # list of tuples 

cur.execute("""CREATE TABLE table1 AS 
       SELECT u.id, u.var1 
       FROM unnest(%s) u(id INT, var1 INT)""", (data,)) 

Tuy nhiên, nó can be tricky with extremely large data.

1

Bất cứ ai sử dụng SQLAlchemy có thể thử phiên bản 1.2 có thêm sự ủng hộ của số lượng lớn chèn sử dụng psycopg2.extras.execute_batch() thay vì executemany khi bạn khởi động cơ của bạn với use_batch_mode = True như:

engine = create_engine(
    "postgresql+psycopg2://scott:[email protected]/dbname", 
    use_batch_mode=True) 

http://docs.sqlalchemy.org/en/latest/changelog/migration_12.html#change-4109

Sau đó, ai đó sẽ phải sử dụng SQLalchmey sẽ không bận tâm để thử kết hợp khác nhau của sqla và psycopg2 và SQL trực tiếp với nhau.

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