2010-10-17 24 views
9

Tôi có một ứng dụng cần cập nhật một lượng lớn dữ liệu qua một số lượng lớn mục nhập. Về cơ bản nó làm một số 7.000 chèn và/hoặc cập nhật nhưng phải mất một thời gian looooong (như gần 9 phút ... trung bình khoảng 0,08 giây cho mỗi truy vấn). Về cơ bản tôi đang tìm kiếm những cải tiến chung để thực hiện nhiều yêu cầu như vậy (tôi không mong đợi một câu trả lời cụ thể cho ví dụ mơ hồ của tôi ... đó chỉ là, hy vọng, giúp giải thích).Tăng tốc số lượng lớn các cập nhật mysql và chèn

Dưới đây là một số mẫu từ profiling các yêu cầu: nauseam quảng cáo

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:30:00-07:00') AND (planet_id = '2010_Gl_581_c') 

INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:45:00-07:00') AND (planet_id = '2010_Gl_581_c') 

INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

Lặp lại (tốt, khoảng 7.000 lần). Đây là bản cập nhật thu thập dữ liệu được tạo trong khoảng thời gian 24 giờ và sau đó thực hiện cập nhật lớn cho cơ sở dữ liệu một lần mỗi ngày. Với giới hạn bit tôi đã cho thấy bạn đang có bất cứ đề nghị để đẩy nhanh quá trình này lên?

Ví dụ ... có nghĩa là, thay vì chọn một dấu thời gian cho mỗi dấu thời gian, hãy thực hiện một lựa chọn cho một phạm vi cùng một lúc và sau đó lặp lại chúng trong tập lệnh?

Mơ hồ như:

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (planet_id = '2010_Gl_581_c') 

assign mà kết quả để $foo và sau đó làm:

foreach ($foo as $bar) 
{ 
    if ($bar['timestamp'] == $baz) // where $baz is the needed timestamp 
    { 
    // do the insert here 
    } 
} 

EDIT: Để thêm một chút để này, một điều mà cải thiện đáp ứng trong tình huống của tôi là để thay đổi một loạt mã đã kiểm tra bản ghi hiện có và đã thực hiện chèn hoặc cập nhật tùy thuộc vào kết quả sử dụng truy vấn sql INSERT... ON DUPLICATE KEY UPDATE. Điều này dẫn đến tăng tốc độ 30% trong trường hợp cụ thể của tôi bởi vì nó cắt ít nhất một chuyến đi tới cơ sở dữ liệu ra khỏi phương trình và hơn hàng nghìn yêu cầu thực sự tăng lên.

Trả lời

16

Một số liên kết hữu ích:

Từ Tài liệu MySQL:

Speed of INSERT Statements nói:

  • Nếu bạn đang chèn nhiều hàng từ cùng một khách hàng cùng một lúc, sử dụng câu lệnh INSERT với nhiều GIÁ TRỊ danh sách này để chèn nhiều hàng vào một thời điểm . Điều này nhanh hơn đáng kể (nhanh hơn nhiều lần trong một số trường hợp) so với sử dụng các câu lệnh INSERT riêng biệt. Nếu bạn đang thêm dữ liệu vào bảng không trống, bạn có thể điều chỉnh biến số bulk_insert_buffer_size thành làm cho việc chèn dữ liệu nhanh hơn nữa.

  • Nếu nhiều khách hàng đang chèn nhiều hàng, bạn có thể nhận được tốc độ cao hơn bằng cách sử dụng câu lệnh INSERT DELAYED.

  • Đối với một bảng MyISAM, bạn có thể sử dụng đồng thời chèn thêm hàng cùng lúc rằng CHỌN tuyên bố là chạy, nếu không có các hàng xóa ở giữa của tập tin dữ liệu.

  • Khi tải bảng từ tệp văn bản, hãy sử dụng LOAD DATA INFILE. Đây là thường nhanh hơn 20 lần so với sử dụng câu lệnh INSERT.

  • Với một số công việc phụ, có thể làm cho LOAD DATA INFILE chạy ngay cả nhanh hơn cho bảng MyISAM khi bảng có nhiều chỉ mục.

+1

+1. Câu trả lời tốt. – sberry

2

Nếu bạn chưa sẵn sàng, sử dụng chuẩn bị phát biểu (thông qua một trong hai mysqli, PDO, hoặc một số thư viện DB khác có hỗ trợ chúng). Sử dụng lại câu lệnh đã được chuẩn bị và chỉ đơn giản là thay đổi các giá trị tham số sẽ giúp tăng tốc mọi thứ, vì máy chủ MySQL chỉ phải phân tích truy vấn một lần.

INSERT s có thể được theo đợt bằng cách cung cấp nhiều bộ VALUES - một truy vấn chèn nhiều hàng nhanh hơn nhiều so với số lượng truy vấn riêng lẻ tương ứng mỗi hàng chèn.

2

Những gì bạn đề xuất là chính xác. Hãy thử giảm số lượng truy vấn bạn gửi đến máy chủ vì điều này sẽ giúp bạn tiết kiệm được nhiều chi phí liên lạc.

Tất nhiên, nếu truy vấn được chọn trong phạm vi truy vấn trả về quá nhiều dữ liệu, thì bạn có thể có một nút cổ chai trên PHP.

1

Tôi có thể sử dụng thủ tục đã lưu nếu có thể và chỉ cần gọi từ mã ứng dụng của tôi. Ngoài ra, tôi muốn suy nghĩ về việc lập chỉ mục thích hợp và có thể thêm một khóa thay thế dựa trên số nguyên cho planet_id là một ký tự 13 byte không phải là biểu diễn trong các phép nối và tra cứu như một số nguyên 4 byte.

(Tôi vừa mới đọc có được ước tính là 10 triệu nghìn tỷ hành tinh sinh sống trong vũ trụ như vậy có lẽ bạn nên sử dụng bigint unsigned: P)

drop procedure if exists update_insert_habitable_planets; 

delimiter # 

create procedure update_insert_habitable_planets 
(
in p_planet_id int unsigned, 
in p_timestamp datetime, 
) 
proc_main:begin 

    start transaction; 

    -- bulk update/insert whatever 

    commit; 

end proc_main # 

delimiter ; 
+0

* "10 triệu nghìn tỷ" * - 10 nghìn tỷ :) – BadHorsie

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