Bạn có thể tăng tốc hoạt động cập nhật hàng loạt bằng một thủ thuật, ngay cả khi máy chủ cơ sở dữ liệu (như trong trường hợp của bạn) có độ trễ rất tệ. Thay vì cập nhật bảng của bạn trực tiếp, bạn sử dụng bảng giai đoạn để chèn dữ liệu mới của bạn rất nhanh, sau đó thực hiện một lần tham gia cập nhật vào bảng đích . Điều này cũng có lợi thế là bạn giảm đáng kể số lượng câu lệnh phải gửi đến cơ sở dữ liệu.
Điều này hoạt động như thế nào với UPDATEs?
Giả sử bạn có một bảng entries
và bạn luôn có dữ liệu mới, nhưng bạn chỉ muốn cập nhật những dữ liệu đã được lưu trữ. Bạn tạo một bản sao của bảng đích entries_stage
của mình chỉ với các trường liên quan trong đó:
entries = Table('entries', metadata,
Column('id', Integer, autoincrement=True, primary_key=True),
Column('value', Unicode(64), nullable=False),
)
entries_stage = Table('entries_stage', metadata,
Column('id', Integer, autoincrement=False, unique=True),
Column('value', Unicode(64), nullable=False),
)
Sau đó, bạn chèn dữ liệu của mình bằng tính năng chèn hàng loạt. Điều này có thể được đẩy nhanh hơn nữa nếu bạn sử dụng cú pháp chèn nhiều giá trị của MySQL, cú pháp này vốn không được SQLAlchemy hỗ trợ, nhưng có thể được xây dựng mà không gặp nhiều khó khăn.
INSERT INTO enries_stage (`id`, `value`)
VALUES
(1, 'string1'), (2, 'string2'), (3, 'string3'), ...;
Cuối cùng, bạn cập nhật các giá trị của bảng đích với các giá trị từ bảng giai đoạn như sau:
UPDATE entries e
JOIN entries_stage es ON e.id = es.id
SET e.value = es.value;
Sau đó, bạn đã hoàn tất.
Thế còn phụ trang thì sao?
Tất nhiên, điều này cũng có tác dụng tăng tốc độ chèn. Vì bạn đã có dữ liệu trong bảng giai đoạn , tất cả những gì bạn cần làm là phát hành một INSERT INTO ... SELECT
câu lệnh, với dữ liệu không có trong bảng đích chưa.
INSERT INTO entries (id, value)
SELECT FROM entries_stage es
LEFT JOIN entries e ON e.id = es.id
HAVING e.id IS NULL;
Điều thú vị về điều này là bạn không phải thực hiện INSERT IGNORE
, REPLACE
hoặc ON DUPLICATE KEY UPDATE
, điều này sẽ tăng khóa chính của bạn, ngay cả khi chúng không làm gì cả .