Cách hiệu quả nhất để hàng loạt truy vấn CẬP NHẬT trong MySQL là gì?


10

Tôi đang viết một ứng dụng cần tuôn ra một số lượng lớn các bản cập nhật cho cơ sở dữ liệu trong một khoảng thời gian dài và tôi đã bị mắc kẹt trong cách tối ưu hóa truy vấn. Hiện tại tôi đang sử dụng INSERT INTO ... VALUES (..), (..) ON DUPLICATE KEY UPDATE, hoạt động để gộp tất cả các giá trị vào một truy vấn, nhưng thực thi chậm trên các bảng lớn. Tôi không bao giờ thực sự cần phải chèn hàng.

Các cách tiếp cận khác mà tôi thấy là cập nhật bằng cách sử dụng SET value = CASE WHEN...(sẽ khó tạo ra do cách tôi xây dựng các truy vấn và tôi không chắc về hiệu suất của CASEhàng trăm / nghìn khóa) và chỉ đơn giản là nhiều kết nối cập nhật. Một trong hai sẽ nhanh hơn phương pháp hiện tại của tôi?

Nó gây trở ngại cho tôi rằng, theo như tôi có thể nói, không có cách thành ngữ, hiệu quả nào để làm điều này trong MySQL. Nếu thực sự không có cách nào nhanh hơn ON DUPLICATE KEY, thì có đáng để chuyển sang PostgreSQL và sử dụng UPDATE FROMcú pháp của nó không?

Bất kỳ đề nghị khác cũng được đánh giá rất cao!

Chỉnh sửa: đây là một trong những bảng được cập nhật thường xuyên. Tôi đã xóa tên cột do chúng không liên quan.

CREATE TABLE IF NOT EXISTS `table` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `a` bigint(20) unsigned NOT NULL DEFAULT '0',
  `b` bigint(20) unsigned NOT NULL DEFAULT '0',
  `c` enum('0','1','2') NOT NULL DEFAULT '0',
  `d` char(32) NOT NULL,
  -- trimmed --
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `c` (`c`),
  KEY `d` (`d`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Đây là trên một máy thử nghiệm và không được sản xuất nên InnoDB không hoàn toàn được điều chỉnh đúng. Tôi không hoàn toàn chắc chắn về cách thức hoạt động của INSERT TỪ, nhưng những gì bạn nói có vẻ đúng. Cập nhật câu hỏi với thông tin bạn yêu cầu.
jli

Câu trả lời:


14

Vì bạn đang sử dụng InnoDBbảng, tối ưu hóa rõ ràng nhất sẽ là nhóm nhiều UPDATEs vào một giao dịch.

Với InnoDB, là một công cụ giao dịch, bạn không chỉ trả tiền cho UPDATEchính nó mà còn cho tất cả các chi phí giao dịch: quản lý bộ đệm giao dịch, nhật ký giao dịch, xóa nhật ký vào đĩa.

Nếu bạn cảm thấy thoải mái về mặt ý tưởng, hãy thử và nhóm 100-1000 UPDATEgiây một lần, mỗi lần được gói như thế này:

START TRANSACTION;
UPDATE ...
UPDATE ...
UPDATE ...
UPDATE ...
COMMIT;

Nhược điểm có thể có:

  • Một lỗi sẽ làm sập toàn bộ giao dịch (nhưng sẽ dễ dàng sửa trong mã)
  • Bạn có thể đợi trong một thời gian dài để tích lũy 1000 UPDATEgiây của mình, vì vậy bạn cũng có thể muốn có một khoảng thời gian chờ
  • Phức tạp hơn về mã ứng dụng của bạn.
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.