Hiệu suất của một thủ tục kích hoạt so với lưu trữ trong MySQL


11

Một bài đăng ở đây trên DBA.StackExchange ( Các thực tiễn tốt nhất để kích hoạt duy trì số sửa đổi trong hồ sơ là gì? ) Đã đưa ra một câu hỏi thú vị (ít nhất là thú vị đối với tôi) về hiệu suất trong MySQL.

Bối cảnh là chúng tôi muốn chèn một bản ghi trong một bảng cho mỗi hàng được cập nhật. Trước khi hàng được cập nhật, chúng tôi muốn lưu trữ một giá trị trước đó và sau đó tăng một trong các cột (cột "phiên bản").

Nếu chúng ta làm điều này trong một kích hoạt, nó hoạt động độc đáo. Đối với MySQL, các kích hoạt là từng hàng , vì vậy nó sẽ là một giải pháp dễ dàng. Chọn dữ liệu hiện tại trong bảng, chèn dữ liệu vào bảng ghi nhật ký và cập nhật cột "phiên bản" trong dữ liệu mới.

Tuy nhiên, có thể di chuyển logic này sang một thủ tục được lưu trữ. Nếu bạn làm điều đó, bạn đang thực hiện thao tác chèn, sau đó tăng cột "phiên bản" trong bảng. Toàn bộ điều sẽ được thiết lập dựa trên.

Vì vậy, khi nói đến việc thực hiện thao tác chèn này, điều này sẽ hiệu quả hơn khi sử dụng phương pháp tiếp cận lưu trữ dựa trên tập hợp hoặc phương pháp tiếp cận dựa trên kích hoạt?

Câu hỏi này dành cho MySQL (vì nó có các kích hoạt theo từng hàng), mặc dù nó có thể áp dụng cho các DBMS kích hoạt từng hàng khác.


1
Một điều cần lưu ý liên quan đến việc đẩy logic phiên bản sang một thủ tục được lưu trữ - bạn sẽ bị gù như thế nào khi ai đó, bằng cách nào đó trực tiếp ghi vào bảng bỏ qua cơ chế kiểm toán của bạn?
billinkc

Tôi đồng ý. Nhưng ở đầu kia của thang đo, có thể bạn muốn cố tình bỏ qua việc đăng nhập này trong một số trường hợp nhất định. Tất nhiên, đó là một câu hỏi hoàn toàn khác . Tôi thực sự chỉ tò mò về ý nghĩa hiệu suất.
Richard

Câu trả lời:


7

Để đơn giản, các trình kích hoạt là cách để thực hiện bất kỳ loại theo dõi thay đổi cơ sở dữ liệu nào. Tuy nhiên, bạn cần lưu ý về những gì xảy ra dưới mui xe khi bạn sử dụng kích hoạt.

Theo Lập trình thủ tục lưu trữ của MySQL , trang 256 dưới phần đầu "Kích hoạt trên đầu" cho biết như sau:

Điều quan trọng cần nhớ là, do sự cần thiết, các trình kích hoạt sẽ thêm chi phí cho câu lệnh DML mà chúng áp dụng. lượng chi phí thực tế sẽ phụ thuộc vào bản chất của trình kích hoạt, nhưng --- vì tất cả các trình kích hoạt MySQL thực thi CHO MACHI ROW --- chi phí có thể nhanh chóng tích lũy cho các câu lệnh xử lý số lượng lớn hàng. Do đó, bạn nên tránh đặt bất kỳ câu lệnh SQL hoặc mã thủ tục đắt tiền nào trong các trình kích hoạt.

Một lời giải thích mở rộng về chi phí kích hoạt được đưa ra trên các trang 529-531. Điểm kết luận từ phần đó nêu sau:

Bài học ở đây là: vì mã kích hoạt sẽ thực thi một lần cho mỗi hàng bị ảnh hưởng bởi câu lệnh DML, nên trình kích hoạt có thể dễ dàng trở thành yếu tố quan trọng nhất trong hiệu suất DML. Mã bên trong thân trình kích hoạt cần phải nhẹ nhất có thể và - đặc biệt - mọi câu lệnh SQL trong trình kích hoạt phải được các chỉ mục hỗ trợ bất cứ khi nào có thể.

Không được đề cập trong cuốn sách là một yếu tố khác khi sử dụng kích hoạt: Khi nói đến ghi nhật ký kiểm toán, xin lưu ý về những gì bạn đăng nhập dữ liệu vào. Tôi nói điều này bởi vì nếu bạn chọn đăng nhập vào bảng MyISAM, mỗi INSERT vào bảng MyISAM sẽ tạo ra một khóa bảng đầy đủ trong suốt INSERT. Điều này có thể trở thành một nút cổ chai nghiêm trọng trong môi trường giao thông cao, giao dịch cao. Ngoài ra, nếu trình kích hoạt chống lại bảng InnoDB và bạn ghi nhật ký các thay đổi trong MyISAM từ bên trong trình kích hoạt, điều này sẽ bí mật vô hiệu hóa tuân thủ ACID (nghĩa là giảm các giao dịch chặn thành hành vi tự động), không thể quay ngược lại.

Khi sử dụng kích hoạt trên bảng InnoDB và ghi nhật ký thay đổi

  • Bảng bạn đăng nhập cũng là InnoDB
  • Bạn đã tắt autocommit
  • Bạn thiết lập các khối GIAO DỊCH BẮT ĐẦU ... CAM KẾT / ROLLBACK triệt để

Theo cách này, nhật ký kiểm toán có thể được hưởng lợi từ CAMIT / ROLLBACK như các bảng chính.

Liên quan đến việc sử dụng các thủ tục được lưu trữ, bạn sẽ phải gọi một cách cẩn thận thủ tục được lưu trữ tại mọi điểm của DML đối với bảng được theo dõi. Người ta có thể dễ dàng bỏ lỡ các thay đổi đăng nhập khi đối mặt với hàng chục ngàn dòng mã ứng dụng. Đặt mã như vậy trong trình kích hoạt sẽ loại bỏ việc tìm tất cả các câu lệnh DML đó.

CAUPAT

Tùy thuộc vào mức độ phức tạp của kích hoạt, nó vẫn có thể là một nút cổ chai. Nếu bạn muốn giảm bớt tắc nghẽn trong ghi nhật ký kiểm toán, có một số điều bạn có thể làm. Tuy nhiên, nó sẽ đòi hỏi một chút thay đổi cơ sở hạ tầng.

Sử dụng phần cứng hàng hóa, tạo thêm hai Máy chủ DB

Điều này sẽ phục vụ để giảm I / O ghi trên cơ sở dữ liệu chính (MD) do ghi nhật ký kiểm toán. Đây là cách bạn có thể thực hiện nó:

Bước 01) Bật ghi nhật ký nhị phân trong cơ sở dữ liệu chính.

Bước 02) Sử dụng máy chủ rẻ tiền, thiết lập MySQL (cùng phiên bản với MD) với tính năng ghi nhật ký nhị phân được bật. Đây sẽ là DM. Thiết lập sao chép từ MD sang DM.

Bước 03) Sử dụng máy chủ rẻ tiền thứ hai, thiết lập MySQL (cùng phiên bản với MD) với tính năng ghi nhật ký nhị phân bị vô hiệu hóa. Thiết lập mỗi bảng kiểm toán để sử dụng --replicate-do-bảng . Đây sẽ là AU. Thiết lập sao chép từ DM sang AU.

Bước 04) mysqldump các cấu trúc bảng từ MD và tải nó vào DM và AU.

Bước 05) Chuyển đổi tất cả các bảng kiểm toán trong MD để sử dụng công cụ lưu trữ BLACKHOLE

Bước 06) Chuyển đổi tất cả các bảng trong DM và AU để sử dụng công cụ lưu trữ BLACKHOLE

Bước 07) Chuyển đổi tất cả các bảng kiểm toán trong AU để sử dụng công cụ lưu trữ MyISAM

Khi xong

  • DM sẽ sao chép từ MD và ghi lại nội dung trong nhật ký nhị phân của nó
  • Với bộ lọc --replicate-do-bảng trên tất cả các bảng kiểm toán, AU sẽ sao chép từ DM

Điều này làm là lưu trữ thông tin kiểm toán trên một máy chủ DB riêng biệt và cũng làm giảm bất kỳ sự suy giảm I / O ghi nào mà MD thường có.


Câu trả lời to lớn +++ 1
b_dubb

1

Đây là một cách tiếp cận để thực hiện hàng loạt cập nhật này.

Ví dụ này

  • bảng_A có id chính PRIMARY
  • Bạn tạo một bảng có tên là bảng_A_Keys2Update chỉ với id là PRIMARY KEY
  • Bạn nhập bảng_A_Keys2Update với id id từ bảng_A bạn biết phải được cập nhật

Để tạo bảng_A_Keys2Update, hãy làm như sau:

CREATE TABLE table_A_Keys2Update SELECT id FROM table_A;
ALTER TABLE table_A_Keys2Update ADD PRIMARY KEY (id);

Sau khi bạn điền vào bảng_A_Keys2Update với các id có số sửa đổi cần tăng lên, hãy thực hiện CẬP NHẬT sau để tăng số sửa đổi của tất cả các hàng có id nằm trong cả bảng_A và bảng_A_Keys2Update:

UPDATE table_A A INNER JOIN table_A_Keys2Update B USING (id)
SET A.revision = A.revision + 1;

Truy vấn một dòng này có thể thay thế một kích hoạt và một thủ tục được lưu trữ.

Tùy chọn, bạn có thể đặt một truy vấn này trong một thủ tục được lưu trữ và gọi nó nếu bạn muốn.


Đó thực sự là Phụ trang mà tôi tò mò. Nếu bạn XÁC NHẬN VÀO kiểm toán CHỌN <bất cứ điều gì> TỪ <sơ cấp_bảng> WHERE <tham số từ thủ tục được lưu trữ> bạn có thể thực hiện chèn hàng loạt. Trong trình kích hoạt, bạn chỉ cần XÁC NHẬN GIÁ TRỊ kiểm toán <dữ liệu từ hàng được cập nhật> . Vì vậy, liệu chèn một dòng, từng hàng sẽ nhanh hơn chèn hàng loạt?
Richard

Để đơn giản, trình kích hoạt sẽ tốt hơn nhiều 1) với điều kiện chính không bao giờ gặp phải tình trạng chèn bulks vào giữa bất kỳ thời gian cao điểm nào, 2) thông tin kiểm toán cần được đọc theo yêu cầu tại bất kỳ thời điểm nào và 3) trang web của bạn là buôn bán thấp.
RolandoMySQLDBA
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.