MariaDB
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> MariaDB

Hiệu suất trình điều khiển trình kết nối Java MariaDB

HIỆU SUẤT KẾT NỐI MARIADB JAVA

Chúng tôi luôn nói về hiệu suất. Nhưng vấn đề luôn là “Đo lường, đừng đoán!”.

Gần đây, rất nhiều cải tiến hiệu suất đã được thực hiện trên Trình kết nối Java MariaDB. Vậy hiệu suất trình điều khiển hiện tại là bao nhiêu?

Hãy để tôi chia sẻ kết quả điểm chuẩn của 3 trình điều khiển jdbc cho phép truy cập vào cơ sở dữ liệu MySQL / MariaDB:DrizzleJDBC, MySQL Connector / J và MariaDB java connector.

Các phiên bản của trình điều khiển là phiên bản GA mới nhất hiện có tại thời điểm viết blog này:

  • MariaDB 1.5.3
  • MySQL 5.1.39
  • Mưa phùn 1.4

BENCHMARK

JMH là một công cụ khung đo điểm chuẩn vi mô của Oracle do Oracle phát triển, được phân phối dưới dạng các công cụ openJDK, sẽ là bộ microbenchmark của java 9 chính thức. Lợi thế đặc biệt của nó so với các khuôn khổ khác là nó được phát triển bởi những người cùng làm việc trong Oracle, những người thực hiện JIT (biên dịch Just In Time) và cho phép tránh hầu hết các cạm bẫy vi điểm chuẩn.

Nguồn điểm chuẩn:https://github.com/rusher/mariadb-java-driver-benchmark.

Các bài kiểm tra khá đơn giản nếu bạn đã quen với java.
Ví dụ:

 public class BenchmarkSelect1RowPrepareText mở rộng BenchmarkSelect1RowPrepareAbstract {@Benchmark public String mysql (MyState state) ném Throwable {return select1RowPrepare (state.mysqlConnectionText, state); } @Benchmark public String mariadb (MyState state) ném Throwable {return select1RowPrepare (state.mariadbConnectionText, state); } @Benchmark public String mưa phùn (trạng thái MyState) ném Throwable {return select1RowPrepare (state.drizzleConnectionText, state); }} public abstract class BenchmarkSelect1RowPrepareAbstract mở rộng BenchmarkInit {private String request ="SELECT CAST (? as char character set utf8)"; public String select1RowPrepare (Kết nối kết nối, trạng thái MyState) ném SQLException {try (PreparedStatement readyStatement =connection.prepareStatement (yêu cầu)) {readyStatement.setString (1, state.insertData [state.counter ++]); try (ResultSet rs =readyStatement.executeQuery ()) {rs.next (); return rs.getString (1); }}}} 

Các thử nghiệm sử dụng truy vấn của INSERT được gửi tới công cụ BLACKHOLE với nhật ký nhị phân bị vô hiệu hóa, để tránh IO và phụ thuộc vào hiệu suất lưu trữ. Điều này cho phép có kết quả ổn định hơn.
(Không sử dụng công cụ lỗ đen và tắt nhật ký nhị phân, thời gian thực hiện sẽ thay đổi tới 10%).

Điểm chuẩn đã được thực thi trên cơ sở dữ liệu MariaDB Server 10.1.17 và MySQL Community Server 5.7.13. Tài liệu sau đây hiển thị kết quả bằng cách sử dụng 3 trình điều khiển với Máy chủ MariaDB 10.1.17. Để có kết quả đầy đủ bao gồm cả những kết quả với MySQL Server 5.7.13, vui lòng xem liên kết ở cuối tài liệu.

MÔI TRƯỜNG

Việc thực thi (máy khách và máy chủ) được thực hiện trên một giọt máy chủ duy nhất trên digitalocean.com bằng cách sử dụng các thông số sau:

  • Môi trường thời gian chạy Java (TM) SE (bản dựng 1.8.0_101-b13) 64bits (phiên bản thực tế mới nhất khi chạy điểm chuẩn này)
  • Ubuntu 16.04 64bits
  • Bộ nhớ 512Mb
  • 1 CPU
  • cơ sở dữ liệu MariaDB “10.1.17-MariaDB”, MySQL Community Server build “5.7.15-0ubuntu0.16.04.1”
    sử dụng các tệp cấu hình mặc định và các tùy chọn bổ sung sau:

    • max_allowed_packet =40M #exchange gói có thể lên đến 40mb
    • character-set-server =utf8 #để sử dụng UTF-8 làm mặc định
    • collation-server =utf8_unicode_ci # để sử dụng UTF-8 làm mặc định

Khi được chỉ ra "ở xa", điểm chuẩn được chạy với máy khách và máy chủ riêng biệt trên 2 máy chủ giống nhau trên cùng một trung tâm dữ liệu với ping trung bình là 0,350ms.

GIẢI THÍCH MẪU KẾT QUẢ

 Đơn vị lỗi điểm chuẩnBenchmarkSelect1RowPrepareText.mariadb 62.715 ± 2.402 µs / opBenchmarkSelect1RowPrepareText.mysql 88.670 ± 3.505 µs / opBenchmarkSelect1RowPrepareText.drizzle 78.672 ± 2.971 µs 

Điều này có nghĩa là truy vấn đơn giản này sẽ mất thời gian trung bình là 62,715 micro giây khi sử dụng trình điều khiển MariaDB với biến thể ± 2,402 micro giây cho 99,9% truy vấn.
Việc thực hiện tương tự bằng trình điều khiển mưa phùn sẽ mất thời gian trung bình là 88,670 micro giây và 78,672 micro giây sử dụng trình kết nối MySQL (thời gian thực thi càng nhỏ càng tốt).

Tỷ lệ phần trăm được hiển thị được đặt theo kết quả đầu tiên mariadb làm tham chiếu (100%), cho phép dễ dàng so sánh các kết quả khác.

SO SÁNH HIỆU SUẤT

Điểm chuẩn sẽ kiểm tra hiệu suất của 3 hành vi chính khác nhau bằng cách sử dụng cùng một cơ sở dữ liệu cục bộ (cùng một máy chủ) và một cơ sở dữ liệu ở xa (một máy chủ giống hệt nhau) trên cùng một trung tâm dữ liệu với ping trung bình là 0,450ms

Các hành vi khác nhau:

Giao thức văn bản

Điều này tương ứng với tùy chọn useServerPrepStmts bị vô hiệu hóa.
Các truy vấn được gửi trực tiếp đến máy chủ với việc thay thế các thông số đã được khử trùng được thực hiện ở phía máy khách.
Dữ liệu được gửi giống như văn bản. Ví dụ:Dấu thời gian sẽ được gửi như văn bản “1970-01-01 00:00:00.000500” sử dụng 26 byte

Giao thức nhị phân

Điều này tương ứng với tùy chọn useServerPrepStmts được kích hoạt (triển khai mặc định trên trình điều khiển MariaDB).
Dữ liệu được gửi dưới dạng nhị phân. Dấu thời gian mẫu “1970-01-01 00:00:00.000500” sẽ được gửi bằng 11 byte.

Có tối đa 3 trao đổi với máy chủ cho một truy vấn:

  1. CHUẨN BỊ - Chuẩn bị câu lệnh để thực thi.
  2. THỰC HIỆN - Gửi tham số
  3. DEALLOCATE PREPARE - Đưa ra một tuyên bố đã chuẩn bị trước.

Xem Tài liệu chuẩn bị máy chủ để biết thêm thông tin.

CHUẨN BỊ kết quả được lưu trữ trong bộ nhớ cache ở phía trình điều khiển (kích thước mặc định 250). Nếu Chuẩn bị đã có trong bộ nhớ cache, PREPARE sẽ không được thực thi, DEALLOCATE sẽ chỉ được thực thi khi PREPARE không được sử dụng nữa và không có trong bộ nhớ cache. Điều đó có nghĩa là một số thực thi truy vấn sẽ có 3 chuyến khứ hồi, nhưng một số sẽ chỉ có một chuyến khứ hồi, gửi một số nhận dạng và tham số PREPARE.

Viết lại

Điều này tương ứng với tùy chọn rewriteBisedStatements được bật.
Viết lại sử dụng giao thức văn bản và chỉ quan tâm đến các lô. Trình điều khiển sẽ viết lại truy vấn để có kết quả nhanh hơn.

Ví dụ:
Chèn vào ab (i) giá trị (?) Với giá trị lô đầu tiên [1] và [2] sẽ được ghi lại thành
Chèn vào ab (i) giá trị (1), (2).

Nếu không thể viết lại truy vấn bằng “nhiều giá trị”, thì việc viết lại sẽ sử dụng nhiều truy vấn:
Chèn vào bảng (col1) giá trị (?) Trên bản cập nhật khóa trùng lặp col2 =? với các giá trị [1,2] và [2,3] sẽ được ghi lại thành
Chèn vào bảng (col1) giá trị (1) trên bản cập nhật khóa trùng lặp col2 =2; Chèn vào bảng (col1) giá trị (3) trên bản cập nhật khóa trùng lặp col2 =4

Nhược điểm của tùy chọn này là:

  • Không thể truy xuất id tăng tự động bằng cách sử dụngStatement.html # getGeneratedKeys ().
  • Nhiều truy vấn trong một lần thực thi được bật. Đó không phải là vấn đề đối vớiPreparedStatement, nhưng nếu ứng dụng sử dụng Statement có thể làm giảm khả năng bảo mật (SQL injection).

* MariaDB và MySQL có 3 hành vi được triển khai, chỉ điều chỉnh giao thức Văn bản.

KẾT QUẢ BENCHMARK

Kết quả trình điều khiển MariaDB

DUY NHẤT CHỌN CÂU HỎI

 private String request ="SELECT CAST (? as char character set utf8)"; public String select1RowPrepare (Kết nối kết nối, trạng thái MyState) ném SQLException {try (PreparedStatement readyStatement =connect.prepareStatement (yêu cầu)) {readyStatement.setString ( 1, state.insertData [state.counter ++]); // 100 byte ngẫu nhiên. try (ResultSet rs =readyStatement.executeQuery ()) {rs.next (); return rs.getString (1); }}} 
 LOCAL DATABASE:BenchmarkSelect1RowPrepareHit.mariadb 58.267 ± 2.270 µs / opBenchmarkSelect1RowPrepareMiss.mariadb 118.896 ± 5.500 µs / opBenchmarkSelect1RowPrepareText.mariadb 62.715 ± 2.402 µs / op 

 DISTANT DATABASE:BenchmarkSelect1RowPrepareHit.mariadb 394.354 ± 13.102 µs / opBenchmarkSelect1RowPrepareMiss.mariadb 709.843 ± 31.090 µs / opBenchmarkSelect1RowPrepareText.mariadb 422.215 ± 15.8 

Khi kết quả CHUẨN BỊ cho truy vấn chính xác này đã có trong bộ nhớ cache (lần truy cập bộ nhớ cache), truy vấn sẽ nhanh hơn (trong ví dụ này là 7,1%) so với sử dụng giao thức văn bản. Do yêu cầu bổ sung trao đổi PREPARE và DEALLOCATE, bộ nhớ cache bỏ lỡ chậm hơn 68,1%.

Điều này nhấn mạnh những lợi thế và bất tiện của việc sử dụng một giao thức nhị phân. Cache HIT rất quan trọng.

CÂU HỎI CHÈN DUY NHẤT

 private String request ="INSERT INTO blackholeTable (charValue) values ​​(?)"; public boolean executeOneInsertPrepare (Kết nối kết nối, String [] datas) ném SQLException {try (PreparedStatement readyStatement =connection.prepareStatement (yêu cầu)) {readyStatement. setString (1, datas [0]); // trả về dữ liệu 100 byte ngẫu nhiên readyStatement.execute (); }} 
 LOCAL DATABASE:BenchmarkOneInsertPrepareHit.mariadb 61.298 ± 1.940 µs / opBenchmarkOneInsertPrepareMiss.mariadb 130.896 ± 6.362 µs / opBenchmarkOneInsertPrepareText.mariadb 68.363 ± 2.686 µs / oppre> 
 DISTANT DATABASE:BenchmarkOneInsertPrepareHit.mariadb 379.295 ± 17.351 µs / opBenchmarkOneInsertPrepareMiss.mariadb 802.287 ± 24.825 µs / opBenchmarkOneInsertPrepareText.mariadb 415.125 ± 14.547> µs / 14.547 

Kết quả cho CHÈN tương tự như kết quả CHỌN.

BATCH:1000 CHÈN CÂU HỎI

 private String request ="INSERT INTO blackholeTable (charValue) values ​​(?)"; public int [] executeBatch (Kết nối kết nối, dữ liệu String []) ném SQLException {try (PreparedStatement readyStatement =connection.prepareStatement (yêu cầu)) { for (int i =0; i <1000; i ++) {readyStatement.setString (1, data [i]); // một dữ liệu 100 byte ngẫu nhiên readyStatement.addBatch (); } trả về readyStatement.executeBatch (); }} 
 CƠ SỞ DỮ LIỆU ĐỊA PHƯƠNG:Chuẩn bịStatementBatch100InsertPrepareHit.mariadb 5.290 ± 0.232 ms / opPrepareStatementBatch100InsertRewrite.mariadb 0.404 ± 0.014 ms / opPrepareStatementBatch100InsertText.mariadb 6.081 ± 0.254 ms / op 
 CƠ SỞ DỮ LIỆU KHỔNG LỒ:Chuẩn bịStatementBatch100InsertPrepareHit.mariadb 7.639 ± 0.476 ms / opPrepareStatementBatch100InsertRewrite.mariadb 1.164 ± 0.037 ms / opPrepareStatementBatch100InsertText.mariadb 8.148 ± 0.563 ms / op  

Sử dụng giao thức nhị phân ở đây có ý nghĩa hơn, có kết quả nhanh hơn 13% so với sử dụng giao thức văn bản.

Chèn được gửi hàng loạt và kết quả được đọc không đồng bộ (tương ứng với optionuseBatchMultiSend). Điều này cho phép có kết quả xa với hiệu suất không xa so với các địa phương đó.

Viết lại có hiệu suất tốt đáng kinh ngạc, nhưng sẽ không có id tự động tăng. Nếu bạn không cần id ngay lập tức và không sử dụng ORM, giải pháp này sẽ là nhanh nhất. Một số ORM cho phép cấu hình xử lý trình tự bên trong để cung cấp id gia tăng, nhưng những chuỗi đó không được phân phối, vì vậy sẽ không hoạt động trên các cụm.

SO SÁNH VỚI NHỮNG NGƯỜI LÁI XE KHÁC

Truy vấn CHỌN với một kết quả hàng

BenchmarkSelect1RowPrepareHit.mariadb 58.267 ± 2.270 µs/opBenchmarkSelect1RowPrepareHit.mysql 73.789 ± 1.863 µs/opBenchmarkSelect1RowPrepareMiss.mariadb 118.896 ± 5.500 µs/opBenchmarkSelect1RowPrepareMiss.mysql 150.679 ± 4.791 µs/opBenchmarkSelect1RowPrepareText.mariadb 62.715 ± 2.402 µs/opBenchmarkSelect1RowPrepareText.mysql 88.670 ± 3.505 µs /opBenchmarkSelect1RowPrepareText.drizzle 78,672 ± 2,971 µs / opBenchmarkSelect1RowPrepareTextHA.mariadb 64,676 ± 2,192 µs / opBenchmarkSelect1RowPrepareTextHA.mysql 137,289 ± 4,872 µs / op 

HA là viết tắt của “Tính sẵn sàng cao” sử dụng
cấu hình Master-Slave (URL kết nối là “jdbc:mysql:replication:// localhost:3306, localhost:3306 / testj”).

Những kết quả này là do rất nhiều sự lựa chọn thực hiện khác nhau. Dưới đây là một số lý do giải thích sự khác biệt về thời gian:

  • Trình điều khiển MariaDB được tối ưu hóa cho UTF-8, cho phép tạo ít mảng byte hơn, tránh sao chép mảng và tiêu thụ bộ nhớ.
  • Triển khai HA:Trình điều khiển MariaDB và MySQL sử dụng Proxyclass động java nằm giữa các đối tượng Statement và socket, cho phép thêm hành vi chuyển đổi dự phòng. Việc bổ sung đó sẽ tiêu tốn chi phí là 2 micro giây cho mỗi truy vấn (62,715 mà không trở thành 64,676 micro giây).
    Trong triển khai MySQL, gần như tất cả các phương thức nội bộ đều được hỗ trợ, thêm chi phí cho rất nhiều phương thức không liên quan đến chuyển đổi dự phòng, thêm tổng chi phí là 50 micro giây cho mỗi truy vấn.

(Mưa phùn không có PREPARE, không có chức năng HA)

“Chọn 1000 hàng”

 private String request ="select * from seq_1_to_1000"; // sử dụng công cụ lưu trữ trình tự riêng tư ResultSet select1000Row (Kết nối kết nối) ném SQLException {try (Statement statement =connection.createStatement ()) {try (ResultSet rs =statement.executeQuery (request)) {while (rs.next ()) { rs.getString (1); } return rs; }} 
 BenchmarkSelect1000Rows.mariadb 244.228 ± 7.686 µs / opBenchmarkSelect1000Rows.mysql 298.814 ± 12.143 µs / opBenchmarkSelect1000Rows.drizzle 406.877 ± 16.585 µs / op 

Khi sử dụng nhiều dữ liệu, thời gian chủ yếu dành cho việc đọc từ socket và lưu trữ trong bộ nhớ để gửi lại cho máy khách. Nếu điểm chuẩn chỉ thực thi SELECT mà không đọc kết quả, thì thời gian thực thi MySQL và MariaDB sẽ tương đương nhau. Vì mục tiêu của truy vấn SELECT là có kết quả, trình điều khiển MariaDB được tối ưu hóa để trả lại kết quả (tránh tạo mảng byte).

“Chèn 1000 hàng”

LOCAL DATABASE:PrepareStatementBatch100InsertPrepareHit.mariadb 5.290 ± 0.232 ms/opPrepareStatementBatch100InsertPrepareHit.mysql 9.015 ± 0.440 ms/opPrepareStatementBatch100InsertRewrite.mariadb 0.404 ± 0.014 ms/opPrepareStatementBatch100InsertRewrite.mysql 0.592 ± 0.016 ms/opPrepareStatementBatch100InsertText.mariadb 6.081 ± 0.254 ms/opPrepareStatementBatch100InsertText.mysql 7.932 ± 0,293 ms / opPrepareStatementBatch100InsertText.drizzle 7,314 ± 0,205 ms / op 
DISTANT DATABASE:PrepareStatementBatch100InsertPrepareHit.mariadb 7.639 ± 0.476 ms/opPrepareStatementBatch100InsertPrepareHit.mysql 43.636 ± 1.408 ms/opPrepareStatementBatch100InsertRewrite.mariadb 1.164 ± 0.037 ms/opPrepareStatementBatch100InsertRewrite.mysql 1.432 ± 0.050 ms/opPrepareStatementBatch100InsertText.mariadb 8.148 ± 0.563 ms/opPrepareStatementBatch100InsertText.mysql 43.804 ± 1,417 ms / opPrepareStatementBatch100InsertText.drizzle 38,735 ± 1,731 ms / op 

Chèn hàng loạt MySQL và Drizzle giống như X INSERT:Trình điều khiển gửi 1 CHÈN, đợi kết quả chèn và gửi chèn tiếp theo. Độ trễ mạng giữa mỗi lần chèn sẽ làm chậm quá trình chèn.

Thủ tục lưu trữ

THỦ TỤC CUỘC GỌI

 // TẠO QUY TRÌNH inoutParam (INOUT p1 INT) begin set p1 =p1 + 1; endprivate String request ="{call inOutParam (?)}"; private String callableStatementWithOutParameter (Kết nối kết nối, trạng thái MyState) ném SQLException {thử (CallableStatement ManagedProc =connection.prepareCall (request)) {ManagedProc.setInt (1, state. functionVar1); // 2 Lưu trữProc.registerOutParameter (1, Loại.INTEGER); StorageProc.execute (); trả về ManagedProc.getString (1); }} 
 BenchmarkCallableStatementWithOutParameter.mariadb 88.572 ± 4.263 µs / opBenchmarkCallableStatementWithOutParameter.mysql 714.108 ± 44.390 µs / op 

Việc triển khai MySQL và MariaDB hoàn toàn khác nhau. Trình điều khiển Mysql sẽ sử dụng nhiều truy vấn ẩn để thu được kết quả đầu ra:

  • SHOW CREATE PROCEDURE testj.inoutParam để xác định các tham số IN và OUT
  • SET @com_mysql_jdbc_outparam_p1 = 1 để gửi dữ liệu theo thông số IN / OUT
  • CALL testj.inoutParam(@com_mysql_jdbc_outparam_p1) thủ tục cuộc gọi
  • SELECT @com_mysql_jdbc_outparam_p1 để đọc kết quả đầu ra

Việc triển khai MariaDB đơn giản bằng cách sử dụng khả năng có tham số OUT trong phản hồi của máy chủ mà không cần bất kỳ truy vấn bổ sung nào. (Đó là lý do chính tại sao trình điều khiển MariaDB yêu cầu máy chủ MariaDB / MySQL phiên bản 5.5.3 trở lên).

KẾT LUẬN

Trình điều khiển MariaDB tuyệt vời!

Giao thức nhị phân có những ưu điểm khác nhau nhưng phụ thuộc vào việc có sẵn các kết quả CHUẨN BỊ trong bộ nhớ đệm. Nếu các ứng dụng có nhiều loại truy vấn khác nhau và cơ sở dữ liệu ở xa, đó có thể không phải là giải pháp tốt hơn.

Viết lại có kết quả đáng kinh ngạc để ghi dữ liệu hàng loạt

Trình điều khiển giữ tốt so với các trình điều khiển khác. Và còn nhiều điều sắp xảy ra, nhưng đó là một câu chuyện khác.

Kết quả thô:

  1. với cơ sở dữ liệu MariaDB 10.1.17 cục bộ, ở xa
  2. với cơ sở dữ liệu MySQL Community Server 5.7.15 (bản dựng 5.7.15-0ubuntu0.16.04.1) cục bộ

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Điều chỉnh Hiệu suất Cơ sở dữ liệu cho MariaDB

  2. Cách MID () hoạt động trong MariaDB

  3. 2 cách trả về hàng chỉ chứa các ký tự không phải chữ và số trong MariaDB

  4. Chọn một proxy cơ sở dữ liệu cho MySQL &MariaDB

  5. Các bước cần thực hiện nếu bạn gặp sự cố MySQL