Dường như Psycopg có một lệnh tùy chỉnh để thực hiện một COPY:SQLAlchemy, Psycopg2 và PostgreSQL COPY
psycopg2 COPY using cursor.copy_from() freezes with large inputs
Có cách nào để truy cập vào chức năng này từ với SQLAlchemy?
Dường như Psycopg có một lệnh tùy chỉnh để thực hiện một COPY:SQLAlchemy, Psycopg2 và PostgreSQL COPY
psycopg2 COPY using cursor.copy_from() freezes with large inputs
Có cách nào để truy cập vào chức năng này từ với SQLAlchemy?
Bạn có thể phải sử dụng psycopg2 để hiển thị chức năng này và bỏ qua các khả năng ORM. Tôi đoán tôi không thực sự thấy lợi ích của ORM trong một hoạt động như vậy anyway vì nó là một chèn số lượng lớn thẳng và đối phó với các đối tượng cá nhân một la một ORM sẽ không thực sự làm cho một toàn bộ rất nhiều ý nghĩa.
câu trả lời được chấp nhận là đúng nhưng nếu bạn muốn nhiều hơn chỉ là nhận xét của EoghanM đi trên sau đây làm việc cho tôi trong việc sao chép một bảng ra CSV ...
from sqlalchemy import sessionmaker, create_engine
eng = create_engine("postgresql://user:[email protected]:5432/db")
ses = sessionmaker(bind=engine)
dbcopy_f = open('/tmp/some_table_copy.csv','wb')
copy_sql = 'COPY some_table TO STDOUT WITH CSV HEADER'
fake_conn = eng.raw_connection()
fake_cur = fake_conn.cursor()
fake_cur.copy_expert(copy_sql, dbcopy_f)
Các sessionmaker
là không cần thiết nhưng nếu bạn đang có thói quen tạo động cơ và phiên làm việc cùng lúc để sử dụng raw_connection
, bạn sẽ cần tách riêng chúng (trừ khi có cách nào đó để truy cập công cụ thông qua đối tượng phiên mà tôi không biết). Chuỗi sql được cung cấp cho copy_expert
cũng không phải là cách duy nhất cho nó, có chức năng cơ bản copy_to
mà bạn có thể sử dụng với tập hợp con các tham số mà bạn có thể truy cập vào truy vấn thông thường COPY
ĐỂ truy vấn. Hiệu suất tổng thể của lệnh có vẻ nhanh đối với tôi, sao chép ra một bảng ~ 20.000 hàng.
http://initd.org/psycopg/docs/cursor.html#cursor.copy_to http://docs.sqlalchemy.org/en/latest/core/connections.html#sqlalchemy.engine.Engine.raw_connection
Nếu động cơ của bạn được cấu hình với một chuỗi kết nối psycopg2 (đó là mặc định, do đó, hoặc "postgresql://..."
hoặc "postgresql+psycopg2://..."
), bạn có thể tạo ra một con trỏ psycopg2 từ một phiên SQL Alchemy sử dụng
cursor = session.connection().connection.cursor()
mà bạn có thể sử dụng để thực thi
cursor.copy_from(...)
Con trỏ sẽ hoạt động trong cùng một giao dịch như phiên của bạn hiện tại. Nếu xảy ra commit
hoặc rollback
, việc sử dụng con trỏ thêm một lần nữa là ném psycopg2.InterfaceError
, bạn sẽ phải tạo một hình mới.
Bạn không cần phải thả xuống psycopg2, sử dụng raw_connection cũng như một con trỏ.
Chỉ cần thực hiện sql như bình thường, thậm chí bạn có thể sử dụng các tham số ràng buộc với text()
:
engine.execute(text('''copy some_table from :csv
delimiter ',' csv'''
).execution_options(autocommit=True),
csv='/tmp/a.csv')
Bạn có thể thả execution_options(autocommit=True)
nếu this PR sẽ được chấp nhận
Chỉ tiết lộ rằng đó là kho lưu trữ mã của bạn, có vẻ như là – Drew
Không, cái được liên kết là "PR này" không phải của tôi kho lưu trữ, đó là kho lưu trữ thông thường/chính thức cho sqlalchemy. OTOH PR rõ ràng là của tôi, đó không phải là một bí mật: Tôi sử dụng cùng một tên người dùng trên cả stackoverflow và bitbucket. Nhưng dù sao, tôi đã vấp phải câu hỏi này trong khi nghiên cứu các ví dụ cho sự thay đổi đó, và mọi thứ tôi đã viết đều đúng. Tôi có thể tránh liên kết PR, nhưng (trong trường hợp nó sẽ được chấp nhận) thì câu trả lời này sẽ gợi ý một đoạn trích lỗi thời, trừ khi tôi hoặc ai đó sẽ nhớ cập nhật nó sau khi thực tế – berdario
Bạn có thể sử dụng:
def to_sql(engine, df, table, if_exists='fail', sep='\t', encoding='utf8'):
# Create Table
df[:0].to_sql(table, engine, if_exists=if_exists)
# Prepare data
output = cStringIO.StringIO()
df.to_csv(output, sep=sep, header=False, encoding=encoding)
output.seek(0)
# Insert data
connection = engine.raw_connection()
cursor = connection.cursor()
cursor.copy_from(output, table, sep=sep, null='')
connection.commit()
cursor.close()
Tôi chèn 200000 dòng trong 5 giây thay vì 4 phút
.210Bạn có thể cung cấp một số chi tiết về những gì ' đối tượng df' là gì? – EoghanM
df là một khung dữ liệu gấu trúc –
Nếu bạn có thể tới các cơ bạn có tất cả các bạn cần phải làm điều này:
engine = create_engine('postgresql+psycopg2://myuser:[email protected]/mydb')
# or
engine = session.engine
# or any other way you know to get to the engine
Bây giờ bạn có thể làm việc.
# isolate a connection
connection = engine.connect().connection
# get the cursor
cursor = connection.cursor()
Dưới đây là một số mẫu cho các tuyên bố COPY để sử dụng với cursor.copy_expert()
, một lựa chọn hoàn chỉnh hơn và linh hoạt hơn copy_from()
hoặc copy_to()
vì nó được chỉ định ở đây: http://initd.org/psycopg/docs/cursor.html#cursor.copy_expert.
# to dump to a file
dump_to = """
COPY mytable
TO STDOUT
WITH (
FORMAT CSV,
DELIMITER ',',
HEADER
);
"""
# to copy from a file:
copy_from = """
COPY mytable
FROM STDIN
WITH (
FORMAT CSV,
DELIMITER ',',
HEADER
);
"""
Kiểm tra các tùy chọn trên có nghĩa là gì và những người khác có thể quan tâm đến tình huống cụ thể của bạn https://www.postgresql.org/docs/current/static/sql-copy.html.
LƯU Ý QUAN TRỌNG: Liên kết đến tài liệu của cursor.copy_expert()
cho biết sử dụng STDOUT để ghi ra tệp và STDIN để sao chép từ tệp. Nhưng nếu bạn nhìn vào cú pháp trên hướng dẫn sử dụng PostgreSQL, bạn sẽ thấy rằng bạn cũng có thể chỉ định tệp cần ghi vào hoặc trực tiếp trong câu lệnh COPY. Đừng làm điều đó, bạn có thể lãng phí thời gian của bạn nếu bạn không chạy root (người chạy Python như root trong quá trình phát triển?) Chỉ cần làm những gì được chỉ ra trong tài liệu của psycopg2 và chỉ định STDIN hoặc STDOUT trong câu lệnh của bạn với cursor.copy_expert()
, nó sẽ ổn thôi.
# running the copy statement
with open('/path/to/your/data/file.csv') as f:
cursor.copy_expert(copy_from, file=f)
# don't forget to commit the changes.
connection.commit()
siêu - có thể truy cập psycopg qua engine.raw_connection() – EoghanM