2011-06-26 42 views
19

Tôi đang làm việc với mô-đun MySQLdb trong Python để tương tác với cơ sở dữ liệu. Tôi có một tình huống mà có một danh sách rất lớn (hàng chục nghìn yếu tố) mà tôi cần phải chèn thành các hàng vào một bảng.Python + MySQL - Chèn số lượng lớn

Giải pháp của tôi ngay bây giờ là tạo tuyên bố lớn INSERT dưới dạng một chuỗi và thực thi nó.

Có cách nào thông minh hơn không?

Trả lời

16

Có cách thông minh hơn.

Vấn đề với chèn hàng loạt là theo mặc định autocommit is enabled do đó, mỗi câu lệnh insert sẽ được lưu vào lưu trữ ổn định trước khi chèn tiếp theo có thể bắt đầu.

Như các ghi chú trang hướng dẫn:

Theo mặc định, MySQL chạy với autocommit chế độ kích hoạt. Điều này có nghĩa là ngay sau khi bạn thực hiện một tuyên bố rằng cập nhật (sửa đổi) một bảng, MySQL lưu trữ bản cập nhật trên đĩa để biến nó thành vĩnh viễn. Để tắt chế độ autocommit, sử dụng câu lệnh sau:

SET autocommit=0; 

Sau khi vô hiệu hóa chế độ autocommit bằng cách thiết lập các biến autocommit để không, thay đổi các bảng giao dịch an toàn (như những cho InnoDB , BDB hoặc NDBCLUSTER) không được thực hiện vĩnh viễn ngay lập tức. Bạn phải sử dụng COMMIT để lưu trữ các thay đổi của bạn vào đĩa hoặc ROLLBACK để bỏ qua các thay đổi.

Đây là một tính năng khá phổ biến của các hệ thống RDBM mà cho rằng tính toàn vẹn của cơ sở dữ liệu là tối quan trọng. Nó làm cho chèn số lượng lớn mất vào thứ tự của 1s cho mỗi chèn thay vì 1ms. Việc thay thế việc tạo một lệnh chèn chồng chéo cố gắng để đạt được cam kết đơn lẻ này có nguy cơ quá tải trình phân tích cú pháp SQL.

+4

Bắt đầu với 1.2.0, MySQLdb vô hiệu hóa tự động theo mặc định, theo yêu cầu của tiêu chuẩn DB-API (PEP-249). source: http://mysql-python.sourceforge.net/FAQ.html – mikewaters

+0

Nếu bạn cảm thấy rằng chèn của bạn vẫn còn chậm hơn họ nên, hãy chắc chắn cũng tinh chỉnh các thiết lập máy chủ mysql của bạn. Trong trường hợp của tôi, 'innodb_buffer_pool_size' của tôi quá nhỏ so với kích thước giao dịch của tôi và bằng cách tăng nó, tôi đã đạt được tăng tốc 40% cho chèn số lượng lớn. Xem: https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool.html – jlh

1

Miễn là bạn đang thực hiện nó như là một INSERT duy nhất và không phải hàng ngàn cá nhân, thì có đây là cách tốt nhất để làm điều đó. Xem ra vì không vượt quá kích thước gói tối đa của mysqls và điều chỉnh nó nếu cần. Ví dụ, điều này đặt gói máy chủ tối đa là 32Mb. Bạn cũng cần làm như vậy trên máy khách.

mysqld --max_allowed_packet=32M 
+0

đây là một hack xung quanh cơ chế giao dịch giải quyết các triệu chứng và không phải nguyên nhân – msw

+0

Bạn có thể mở rộng một chút về điều đó không? Hoặc nói những gì bạn sẽ làm thay vào đó? – justinhj

+0

@msw Sẽ nhanh hơn khi phát hành các lệnh INSERT * với các giao dịch * – Will

11

Nếu bạn phải chèn số lượng dữ liệu rất lớn tại sao bạn đang cố chèn tất cả chúng vào một insert? (Điều này sẽ không cần thiết đặt tải trên bộ nhớ của bạn trong việc thực hiện lớn này insert chuỗi và cũng trong khi thực hiện nó. Ngoài ra đây không phải là một giải pháp rất tốt nếu dữ liệu của bạn được chèn vào là rất rất lớn.)

Tại sao không bạn đặt một hàng cho mỗi lệnh insert trong db và đặt tất cả các hàng bằng cách sử dụng một for...loop và cam kết tất cả các thay đổi cuối cùng?

con = mysqldb.connect(
         host="localhost", 
         user="user", 
         passwd="**", 
         db="db name" 
        ) 
cur = con.cursor() 

for data in your_data_list: 
    cur.execute("data you want to insert: %s" %data) 

con.commit() 
con.close() 

(Hãy tin tôi, đây thực sự là nhanh nhưng nếu bạn đang nhận được kết quả chậm hơn sau đó nó có nghĩa là bạn autocommit phải True.Đặt nó thành Falsemsw nói.)

+0

Nếu có một tuyên bố cho mỗi lần chèn, nó sẽ không được rất chậm? Tôi không nhớ sử dụng bộ nhớ. Nó sẽ chỉ là megabyte vì vậy tôi không quan tâm. – Mike

+0

không có nó sẽ không được làm chậm đó là những gì tôi muốn nói ... miễn là bạn không cam kết ở giữa vòng lặp. Hãy thử cả hai và xem nếu bạn không tin tôi ... –

+0

Trong MyISAM (công cụ tôi đang sử dụng) không cam kết thực hiện hoàn toàn sau khi thực hiện? – Mike

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