Có một số yếu tố trong công việc ở đây:
- Độ trễ của mạng và độ trễ trong cả chuyến đi
- Chi phí chung cho mỗi câu lệnh trong PostgreSQL
- Chuyển đổi ngữ cảnh và độ trễ của trình lập lịch
-
COMMIT
chi phí, nếu đối với những người thực hiện một lần cam kết cho mỗi lần chèn (bạn thì không) -
COPY
-các tối ưu hóa cụ thể cho việc tải hàng loạt
Độ trễ của mạng
Nếu máy chủ ở xa, bạn có thể đang "trả" thời gian cố định cho mỗi câu lệnh "giá", chẳng hạn như 50 mili giây (1/5 giây). Hoặc nhiều hơn nữa đối với một số DB được lưu trữ trên đám mây. Vì lần chèn tiếp theo không thể bắt đầu cho đến khi lần chèn cuối cùng hoàn thành thành công, điều này có nghĩa là tối đa của bạn tốc độ chèn là 1000 / hàng theo chu kỳ-độ trễ-tính bằng mili giây mỗi giây. Ở độ trễ 50ms ("thời gian ping"), đó là 20 hàng / giây. Ngay cả trên một máy chủ cục bộ, độ trễ này là khác. Wheras COPY
chỉ cần điền vào các cửa sổ gửi và nhận TCP, đồng thời truyền các hàng nhanh như DB có thể viết chúng và mạng có thể chuyển chúng. Nó không bị ảnh hưởng nhiều bởi độ trễ và có thể chèn hàng nghìn hàng mỗi giây trên cùng một liên kết mạng.
Chi phí mỗi câu lệnh trong PostgreSQL
Ngoài ra còn có chi phí để phân tích cú pháp, lập kế hoạch và thực hiện một câu lệnh trong PostgreSQL. Nó phải có khóa, mở tệp quan hệ, tra cứu chỉ mục, v.v. COPY
cố gắng thực hiện tất cả điều này một lần, khi bắt đầu, sau đó chỉ tập trung vào việc tải các hàng nhanh nhất có thể.
Chi phí chuyển đổi nhiệm vụ / ngữ cảnh
Có thêm chi phí thời gian phải trả do hệ điều hành phải chuyển đổi giữa các bưu điện chờ đợi một hàng trong khi ứng dụng của bạn chuẩn bị và gửi nó, sau đó ứng dụng của bạn chờ phản hồi của các bưu điện trong khi các bưu điện xử lý hàng. Mỗi khi bạn chuyển từ cái này sang cái khác, bạn sẽ lãng phí một ít thời gian. Có thể lãng phí nhiều thời gian hơn để tạm ngừng và tiếp tục trạng thái hạt nhân mức thấp khác nhau khi các quy trình vào và rời khỏi trạng thái chờ.
Bỏ lỡ các tối ưu hóa COPY
Trên hết, COPY
có một số tối ưu nó có thể sử dụng cho một số loại tải. Ví dụ:nếu không có khóa nào được tạo và bất kỳ giá trị mặc định nào là hằng số, thì nó có thể tính toán trước chúng và bỏ qua hoàn toàn trình thực thi, tải nhanh dữ liệu vào bảng ở cấp độ thấp hơn để hoàn toàn bỏ qua một phần công việc bình thường của PostgreSQL. Nếu bạn CREATE TABLE
hoặc TRUNCATE
trong cùng một giao dịch, bạn COPY
, nó có thể thực hiện nhiều thủ thuật hơn nữa để tải nhanh hơn bằng cách bỏ qua việc lưu giữ sổ giao dịch thông thường cần thiết trong cơ sở dữ liệu nhiều khách hàng.
Mặc dù vậy, COPY
của PostgreSQL vẫn có thể làm nhiều hơn nữa để tăng tốc mọi thứ, những thứ mà nó vẫn chưa biết cách thực hiện. Nó có thể tự động bỏ qua cập nhật chỉ mục sau đó xây dựng lại chỉ mục nếu bạn đang thay đổi nhiều hơn một tỷ lệ nhất định của bảng. Nó có thể cập nhật chỉ mục hàng loạt. Nhiều hơn nữa.
Cam kết chi phí
Một điều cuối cùng cần xem xét là chi phí cam kết. Nó có thể không phải là vấn đề đối với bạn vì psycopg2
mặc định mở một giao dịch và không cam kết cho đến khi bạn yêu cầu. Trừ khi bạn bảo nó sử dụng autocommit. Nhưng đối với nhiều trình điều khiển DB, autocommit là mặc định. Trong những trường hợp như vậy, bạn sẽ thực hiện một cam kết cho mỗi INSERT
. Điều đó có nghĩa là một đĩa phẳng, nơi máy chủ đảm bảo nó ghi tất cả dữ liệu trong bộ nhớ vào đĩa và yêu cầu các đĩa ghi vào bộ nhớ đệm của riêng chúng để lưu trữ liên tục. Quá trình này có thể mất một khoảng thời gian lâu thời gian và thay đổi rất nhiều tùy theo phần cứng. Máy tính xách tay NVMe BTRFS dựa trên SSD của tôi chỉ có thể thực hiện 200 fsync / giây, so với 300.000 lần ghi / giây không đồng bộ hóa. Vì vậy, nó sẽ chỉ tải 200 hàng / giây! Một số máy chủ chỉ có thể thực hiện 50 fsync / giây. Một số có thể làm được 20.000. Vì vậy, nếu bạn phải cam kết thường xuyên, hãy cố gắng tải và cam kết theo lô, thực hiện chèn nhiều hàng, v.v. Vì COPY
chỉ có một cam kết cuối cùng, chi phí cam kết là không đáng kể. Nhưng điều này cũng có nghĩa là COPY
không thể phục hồi từ các lỗi một phần thông qua dữ liệu; nó hoàn tác toàn bộ tải hàng loạt.