MySQL LOAD DATA INFILE chậm 80% sau một vài lần nhập dữ liệu với công cụ InnoDB


14

Tôi đang tải tệp 100 GB qua LOAD DATA INFILE. Tôi đã thành công tốt đẹp với MyISAM, một vài giờ và đã hoàn thành.

Tôi đang dùng thử ngay bây giờ bằng InnoDB. Tải bắt đầu nhanh với tốc độ trên 10MB / giây (xem tốc độ tăng trưởng tệp bảng, file_per_tableđược bật).

Nhưng sau khoảng 5 GB dữ liệu, nó chậm lại trong phạm vi 2-4 MB / giây, khi tôi nhận được hơn 20 GB, nó đã giảm xuống khoảng 2 MB / giây.

Kích thước vùng đệm của InnoDB là 8G. Và tôi đã thực hiện các thao tác sau trước khi chạy lệnh LOAD DATA INFILE:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

Tôi không thể thấy lý do tại sao nó bắt đầu tốt và chậm lại theo thời gian.

Ngoài ra, sử dụng cùng các cài đặt, tôi đã chạy cùng một lệnh LOAD DATA INFILE với bảng bằng InnoDB và MyISAM và bộ dữ liệu thử nghiệm 5 GB, MyISAM nhanh hơn 20 lần:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

Bất cứ điều gì khác tôi nên xem xét cố gắng? Công cụ MyISAM có thể theo kịp tốc độ tải tốt hơn nhiều.


Chi tiết bổ sung:

  • Tôi đã thử tải các tệp riêng lẻ, không có sự khác biệt.

  • Tình cờ, tôi có 150 tệp 500 MB mỗi tệp, trong mỗi tệp được sắp xếp các khóa.

  • Sau khi nhận được 40 GB trong một đêm, 12 giờ sau, tốc độ tải xuống còn 0,5 MB / giây, nghĩa là hoạt động thực tế là không thể.

  • Tôi không tìm thấy bất kỳ câu trả lời nào khác cho các câu hỏi tương tự trên các diễn đàn khác, dường như với tôi rằng InnoDB không hỗ trợ tải một lượng lớn dữ liệu vào các bảng có kích thước vài GB.

Câu trả lời:


7

QUAN SÁT # 1

Tôi nhận thấy bạn tắt autocommit. Điều đó sẽ chồng chất rất nhiều dữ liệu trong ibdata1. Tại sao?

Có bảy (7) lớp thông tin được lưu trữ trong ibdata1:

  • Trang dữ liệu cho bảng InnoDB
  • Trang chỉ mục cho các bảng InnoDB
  • Từ điển dữ liệu
  • Bộ đệm đôi
    • Mạng lưới an toàn để ngăn chặn tham nhũng dữ liệu
    • Giúp bỏ qua hệ điều hành cho bộ nhớ đệm
  • Chèn bộ đệm (Hợp lý hóa các thay đổi cho chỉ mục phụ)
  • Phân đoạn rollback
  • Hoàn tác Nhật ký
  • Nhấn vào đây để xem một đại diện hình ảnh của ibdata1

Một số thông tin này được hiển thị cho một số giao dịch nhất định tùy thuộc vào mức độ cô lập. Những hành động như vậy có thể tạo ra các khóa chính không mong muốnnhiều dữ liệu ảo . Khi hai điều này tăng lên, bạn nên mong đợi một sự chậm lại công bằng.

Khuyến nghị: Để lại autocommit trên

QUAN SÁT # 2

Tôi thấy bạn có điều này:

alter table item_load disable keys;

Các phím DISABLE không hoạt động với InnoDB . Đây là lý do tại sao:

  • MyISAM: DISABLE KEYSchỉ cần tắt Cập nhật chỉ mục phụ cho bảng MyISAM. Khi bạn khối lượng INSERT vào bảng MyISAM với các khóa bị vô hiệu hóa sẽ dẫn đến tải bảng nhanh cùng với việc xây dựng KHÓA CHÍNH và tất cả các chỉ mục duy nhất. Khi bạn chạy ENABLE KEYS, tất cả các Chỉ mục phụ được xây dựng tuyến tính trên bảng và được thêm vào .MYD.
  • InnoDB: Như được hiển thị trong hình ảnh bên trong của InnoDB, bảng biểu hệ thống ibdata1có cấu trúc dành riêng cho các mục nhập chỉ mục phụ. Hiện tại, không có quy định nào để xử lý các chỉ mục giống như MyISAM.

Để minh họa điều này, hãy lưu ý nỗ lực của tôi để chạy các phím DISABLE trên bảng InnoDB trong MySQL

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

QUAN SÁT # 3

Bạn nhận thấy rằng MyISAM tải nhanh hơn 20 lần so với InnoDB. Bạn có muốn điều đó nhanh hơn 24-25 lần không? Sau đó chạy như sau:

ALTER TABLE item_load ROW_FORMAT=Fixed;

Điều này sẽ tăng tốc độ INSERT lần 20-25% mà không có bất kỳ Thay đổi DDL nào khác . Tác dụng phụ: Bảng MyISAM có thể tăng kích thước 80% -100%, có thể lớn hơn.

Bạn cũng có thể chạy cái này trên bảng InnoDB, nhưng hành vi tuân thủ ACIDMVCC của InnoDB vẫn sẽ là nút cổ chai về hiệu suất của nó, đặc biệt là nếu các trường VARCHAR tăng đáng kể được ghi vào ibdata1.


Hai quan sát đầu tiên là những điều tôi đã cố gắng thêm vào để khắc phục sự cố sau khi tôi nhận thấy nó lần đầu tiên, nỗ lực đầu tiên của tôi là tự nhiên để innodb một mình (chỉ cần tắt đăng nhập bin). Theo quan sát thứ 3, kích thước dữ liệu của tôi có độ dài thay đổi lớn, tôi cho rằng đây sẽ là một vấn đề? Tôi cảm thấy như tôi chỉ cần giữ cái bàn này.
David park

6

Câu trả lời cuối cùng cho câu hỏi này là không sử dụng InnoDB cho một bảng tham chiếu lớn. MyISAM đang hét rất nhanh, gần thông lượng đầy đủ của tốc độ đĩa cho toàn bộ tải, InnoDB sa lầy. MyISAM là đơn giản, nhưng trong trường hợp này là các yêu cầu của bảng này. Đối với một bảng tham chiếu đơn giản với tải số lượng lớn qua LOAD DATA INFILE, MyISAM là con đường để đi, cho đến nay là rất tốt.

Nhưng lưu ý rằng nếu bạn chạy các bảng MyISAM và InnoDB, cả hai bạn sẽ cần xem xét cấp phát bộ nhớ cho 2 cơ chế bộ đệm, mỗi công cụ có bộ nhớ đệm riêng cần phân bổ bộ nhớ riêng.


5

Bạn có thể thử chia các tệp đầu vào thành các phần nhỏ hơn.

Cá nhân tôi sử dụng http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html cho việc này.

Điều gì xảy ra nếu bạn nhận được một khóa bảng cho bảng trong quá trình nhập? Có thể khóa hàng của InnoDB làm chậm nó (MyISAM sử dụng khóa bảng).

Bạn cũng có thể đọc ở đây để biết thêm ý tưởng: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql


Các tệp của tôi đã có 500 MB, tôi đã chuyển tất cả chúng qua một ống có tên duy nhất để tải dễ dàng hơn, nhưng tôi sẽ thử phương pháp này ngay bây giờ.
David park

Không thấy bất kỳ sự khác biệt nào ở đây, khá nhanh, tôi thấy tốc độ giảm từ việc mở rộng 11MB / giây của tệp DB xuống còn 6 MB (sau khoảng 2 GB) dữ liệu và nó tiếp tục giảm. Tôi đang tải tất cả các tệp trong một vòng lặp for, các cuộc gọi mysql riêng biệt.
David park

Các tập tin đầu tiên được tải trong 54s, 2 trong 3m39s, thứ 3 trong 3m9s, 4m7s, 5m21s, v.v. tất cả các tập tin aprox cùng kích thước.
David park

2

Nếu PK của bạn không phải là AUTO_INCREMENT hoặc dữ liệu trong tệp csv không được sắp xếp trên PK thì điều đó có thể ảnh hưởng đến hiệu suất của tải dữ liệu. Vì bảng trong MySQL là một chỉ mục do đó tất cả dữ liệu được lưu trữ theo thứ tự được sắp xếp, nếu giá trị PK không có trên AUTO_INCREMENT thì MySQL phải thực hiện nhiều dịch chuyển dữ liệu để có được dữ liệu được lưu theo thứ tự được sắp xếp. Đây là lý do tải dữ liệu chậm hơn khi kích thước bảng bắt đầu tăng.

Tôi đang tải tệp csv 91GB với PK trên AUTO_INCREMENT bằng LOAD DATA INFILE và tôi không thấy bất kỳ sự sụt giảm nào trong thông lượng của mình. Tôi đang nhận được 140K đến 145K chèn mỗi giây. Sử dụng Percona MySQL 5.6,38

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.