IO đĩa cao, làm thế nào để giảm thiểu?


8

Tôi là một lập trình viên, không phải là một DBA. Hãy nhẹ nhàng :)

Tổng quat

  • InnoDB, MySQL
  • kịch bản mod_perl, kết nối liên tục
  • kịch bản được gọi cứ sau 20 giây bởi hàng ngàn người dùng

Vấn đề

  • High Disk IO (có lẽ là do cập nhật [?]) Làm chậm mọi thứ, tạo ra một nút cổ chai lớn.

Truy vấn

  1. CẬP NHẬT [bảng đơn] SET refreshTime vào dấu thời gian hiện tại, với hai lần kiểm tra cùng bảng trong mệnh đề WHERE
  2. CHỌN COUNT (*) [tham gia bốn bảng, với các chỉ mục] và một loạt các AND trong mệnh đề WHERE (vẫn khá đơn giản)
  3. CHỌN a, b [nối bốn bảng, cùng bốn bảng] và một bó AND trong mệnh đề WHERE (cũng khá đơn giản)

Bộ nhớ cache truy vấn được bật.

Các giải pháp?

  • Tôi không phải là một DBA, nhưng tôi nghi ngờ rằng có thể có một bảng trong RAM định kỳ (cứ sau 10 giây?) Cập nhật vào đĩa và trong trường hợp xảy ra lỗi nghiêm trọng, sẽ tự động điền vào bảng RAM từ bảng đĩa khi khởi động lại, nhưng tôi không biết liệu nó có thực sự khả thi hay không, nếu đó là giải pháp tốt nhất hoặc có những lựa chọn nào khác ngoài đó.
  • Bất kỳ suy nghĩ hoặc đề nghị? Một lần nữa, tôi là một lập trình viên nên nếu ai đó biết ai đó làm việc này với một khoản phí hoặc có thể chỉ cho tôi các tài nguyên rất cụ thể, tôi sẽ rất cảm kích.

~~~~~~~

CREATE TABLE `openInvitations` (
`id` int(99) NOT NULL auto_increment,
`createTime` timestamp NULL default NULL,
`repAcceptTime` timestamp NULL default NULL,
`rep_id` varchar(64) NOT NULL default '',
`repRefreshTime` timestamp NULL default NULL,
`customer_macAddr` varchar(14) NOT NULL default '',
`customerRefreshTime` timestamp NULL default NULL,
`stage` char(1) NOT NULL default 'P',
`parent` varchar(25) default NULL,
`reason` varchar(64) default NULL,
PRIMARY KEY  (`rep_id`,`customer_macAddr`),
UNIQUE KEY `id` (`id`),
KEY `customer_macAddr` (`customer_macAddr`),
CONSTRAINT `openInvitations_ibfk_1` FOREIGN KEY (`rep_id`) REFERENCES `rep` (`id`),
CONSTRAINT `openInvitations_ibfk_2` FOREIGN KEY (`customer_macAddr`) REFERENCES `customer` (`macAddr`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1
id select_type loại bảng có thể_key key key_len ref rows Extra
1 SIMPLE oi ref PRIMARY, customer_macAddr customer_macAddr 16 const 1 Sử dụng ở đâu; Sử dụng chỉ mục
1 SIMPLE r eq numf PRIMARY, FK nump_1 PRIMary 66 xxx.oi.rep_id 1 Sử dụng ở đâu
1 SIMPLE s eq numf PRIMARY, FK_subscacker_1 PRIMARY 27 xxx.r.subscacker_id 1 Sử dụng ở đâu
1 SIMPLE c eq numf PRIMary PRIMary 4 xxx.s.charge_id 1 Sử dụng ở đâu
id select_type loại bảng có thể_key key key_len ref rows Extra
1 SIMPLE oi ref PRIMARY, customer_macAddr customer_macAddr 16 const 1 Sử dụng ở đâu
1 SIMPLE r eq numf PRIMARY, FK nump_1 PRIMary 66 xxx.oi.rep_id 1 Sử dụng ở đâu
1 SIMPLE s eq numf PRIMARY, FK_subscacker_1 PRIMARY 27 xxx.r.subscacker_id 1 Sử dụng ở đâu
1 SIMPLE c eq numf PRIMary PRIMary 4 xxx.s.charge_id 1 Sử dụng ở đâu
id select_type loại bảng có thể_key key key_len ref rows Extra
1 SIMPLE openInvitations TẤT CẢ khách hàng_macAddr NULL NULL NULL 5258 Sử dụng ở đâu

Sau khi sửa truy vấn:

id select_type loại bảng có thể_key key key_len ref rows Extra
1 SIMPLE openInvitations ref customer_macAddr customer_macAddr 16 const 1 Sử dụng ở đâu

3
Xin chào, chào mừng bạn đến với Quản trị viên Cơ sở dữ liệu . Để bắt đầu, bạn sẽ cần cung cấp EXPLAINđầu ra cho các truy vấn đã chọn của bạn và SHOW CREATE TABLE updateTableđể chúng tôi trợ giúp. Đây có lẽ là một vấn đề lập chỉ mục.
Derek Downey

Cảm ơn. Tôi đã đính kèm thông tin được yêu cầu ở trên. Nếu bạn cần GIẢI THÍCH cho CẬP NHẬT hoặc bất cứ điều gì khác, xin vui lòng cho tôi biết.
Vũ trường

+1 để tự khắc phục :) Đôi khi, giải thích chi tiết vấn đề có thể cho bạn biết lỗi của bạn ở đâu!
Dave Rix

1
Tôi khuyên bạn nên thêm câu trả lời của riêng mình, hiển thị các phiên bản truy vấn cũ và mới, sau một vài ngày bạn có thể chấp nhận câu trả lời của riêng mình và sau đó câu hỏi này sẽ không xuất hiện trong danh sách "chưa được trả lời" :)
Dave Rix

Câu trả lời:


7

Như DTest đã chỉ ra, cung cấp thêm thông tin về vấn đề của bạn.

Về bộ nhớ đệm, bạn có thể có thể tăng kích thước nhóm bộ đệm innodb của mình để cho phép nhiều dữ liệu và chỉ mục được lưu trong bộ nhớ. Nếu bạn có các cập nhật thường xuyên, bạn có thể không được hưởng lợi từ bộ đệm truy vấn và có thể tốt hơn khi sử dụng RAM đó cho nhóm bộ đệm innodb.

Nếu bạn muốn đặt tất cả dữ liệu và chỉ mục của mình vào RAM, thì MySQL Cluster có thể là câu trả lời của bạn.

EDIT
Có vẻ như các câu lệnh CHỌN của bạn đang sử dụng các chỉ mục thích hợp. Bạn có thể cung cấp một kế hoạch giải thích cho tuyên bố cập nhật của bạn? Bạn sẽ phải viết lại nó dưới dạng một câu lệnh CHỌN để làm điều đó. Thực hiện SELECT * FROMcùng một bảng và với mệnh đề where giống như câu lệnh CẬP NHẬT của bạn.


3
George nghĩ rằng tôi đã tìm thấy nó. :) Tôi nghĩ rằng đó là một lỗi trong chính truy vấn, mặc dù nó hoạt động, đang cập nhật hàng nghìn hàng nhiều hơn mức cần thiết. Sẽ chạy qua đêm và cập nhật vào buổi sáng. Cảm ơn bạn!
Vũ trường

3
Nó tốt hơn nhiều. Vấn đề là tôi đã không có chìa khóa trong một trong các OR của mình. Các nghi thức cộng đồng DBA StackExchange ở đây là gì? Tôi có đánh dấu câu trả lời này là "đúng" hay trả lời câu hỏi của riêng tôi và đánh dấu là đúng?
Vũ trường

Tốt Tôi vẫn còn mới ở đây, vì vậy tôi không biết nghi thức đúng đắn. Đây là một câu hỏi để hỏi trên trang web DBA meta.
dabest1

Sẽ thế nào nếu bạn chỉnh sửa câu trả lời của mình để kiểm tra HOẶC trong bản cập nhật và tôi sẽ đánh dấu nó là chính xác? :)
Sàn nhảy

@Disco, hãy tiếp tục và tạo câu trả lời của bạn với lời giải thích và đánh dấu nó là chính xác. Tôi ok với điều đó.
dabest1

5

Vấn đề là kết quả của việc không bao gồm khóa trong một trong các câu lệnh OR của tôi trong CẬP NHẬT.

Hat tip cho "dabest1" để giúp tôi tìm câu trả lời.

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.