2014-09-07 17 views
6

Tôi có vòng lặp for mà trải qua hàng triệu đối tượng. Cách đề xuất để cam kết điều này là gì? Dưới đây là một vài ví dụ mà tôi đã nghĩ đến:Cập nhật hàng triệu hàng trong MySQL - khi nào cam kết

# after each 
for item in items: 
    cursor.execute() 
    conn.commit() 

# at the end 
for item in items: 
    cursor.execute() 
conn.commit() 

# after N items 
for n, item in enumerate(items): 
    cursor.execute() 
    if n % N == 0: 
     conn.commit() 
conn.commit() 

Điều nào ở trên sẽ hiệu quả nhất?

+0

IMO nếu bạn không sử dụng giao dịch thì tốt nhất nên bật trực tiếp [autocommit] (http://stackoverflow.com/a/384452/2629998) trên đối tượng DB. Nếu không, hãy cam kết cuối cùng nếu bạn hài lòng với kết quả hoặc quay lại nếu có điều gì đó xấu xảy ra trong thời gian chờ đợi. –

+0

Tại sao không thử và tìm hiểu, trên bản sao của tập dữ liệu thực tế của bạn? Tôi sẽ nói một trong hai cái sau. Tất nhiên, nếu chương trình bị loại ra, bạn không muốn phải chạy quá nhiều lần cập nhật nữa - vì vậy điều cuối cùng có vẻ hợp lý với tôi. – halfer

+0

Tôi muốn có khuynh hướng gợi ý ở cuối. – hd1

Trả lời

4

Bạn đang hỏi, tôi nên cam kết ...

  1. chỉ một lần vào cuối hoạt động khổng lồ
  2. sau mỗi lần cập nhật hàng
  3. sau mỗi lần N mặt hàng.

Trước hết, nếu bạn đang làm việc với MyISAM, đừng lo lắng về điều đó. MyISAM không thực hiện giao dịch.

Nếu hệ thống của bạn không bị hỏng bằng cách cam kết chỉ một số thay đổi hàng của bạn, bạn nên cam kết sau mỗi N mục. Đó là bởi vì cam kết sau mỗi mục sẽ làm chậm quá trình xử lý của bạn rất nhiều. Chỉ cam kết một lần vào cuối của hoạt động rất lớn có khả năng hoặc là để thổi ra không gian rollback của bạn, hoặc mất một thời gian dài không thể đoán được trong thời gian đó người dùng cơ sở dữ liệu khác của bạn sẽ có sự chậm lại.

Tôi đã trải qua vô số lần này. Bất kỳ N lớn hơn khoảng 20 sẽ làm tốt.

1

Có thể cho rằng "ở cuối" một, kể từ khi bạn BEGINCOMMIT chỉ một lần và đó là một giao dịch duy nhất với phạm vi riêng của mình. Nó dễ dàng hơn từ quan điểm đồng thời: về cơ bản giao dịch nói: đây là bảng của tôi bây giờ, không chạm vào nó bất cứ ai.

Nếu bạn cam kết nhiều lần (hai giải pháp còn lại), bạn BEGINCOMMIT giao dịch nhiều lần (có giao dịch tiếp theo bắt đầu ngay sau khi bạn cam kết). Điều này có nghĩa là nhiều cơ hội bị gián đoạn từ các hoạt động DB đang diễn ra khác. Ngoài ra - những hoạt động đó mất thời gian.

Tuy nhiên, bạn nên chạy điểm chuẩn mô phỏng trường hợp sử dụng của mình. Tôi muốn được tò mò muốn biết nếu tùy thuộc vào một số điều kiện (số hàng để chèn, cấu hình phiên, loại dữ liệu, chỉ mục được sử dụng) một hoặc các giải pháp khác có thể chiếm ưu thế.

+0

Chỉ cần đoán - cam kết chỉ một lần có thể mở rộng bộ đệm đang chờ xử lý vượt qua giới hạn bộ nhớ của nó, đó là lý do tại sao tôi sẽ ưu tiên các cam kết thông thường. Tôi không biết đủ về MySQL tuy nhiên để có một cái nhìn về điều đó. Bạn nói đúng về điểm chuẩn! – halfer

+0

Vâng, đó là vấn đề hiển nhiên với một cam kết lớn. Nó thực sự phụ thuộc vào dữ liệu bạn đang chèn - hàng triệu hàng cho một bảng liên kết đơn giản (INT, INT) là n_millions * 8 MB - điều đó không nhiều. Ngoài ra, một lưu ý: Tôi chỉ có kinh nghiệm với InnoDB. – PawelP

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