Hướng dẫn mysql update json field - trường json cập nhật mysql

MySQL 8.0 giới thiệu cập nhật một phần các giá trị JSON, đây là một cải tiến hiệu suất tốt cho các ứng dụng thường xuyên cập nhật các phần nhỏ của các tài liệu JSON lớn. Trước đây, trong MySQL 5.7, bất cứ khi nào bạn thực hiện thay đổi tài liệu JSON được lưu trữ, tài liệu JSON mới đầy đủ sẽ được ghi vào cơ sở dữ liệu, ngay cả khi bản cập nhật chỉ thay đổi một vài byte trong tài liệu. Điều mới trong MySQL 8.0, là MySQL có thể nhận ra rằng các câu lệnh cập nhật nhất định có thể sửa đổi các tài liệu JSON tại chỗ và đối với các câu lệnh này, nó sẽ cung cấp cho công cụ lưu trữ các bản vá mô tả các sửa đổi. Công cụ lưu trữ có thể sử dụng các bản vá này để viết lượng dữ liệu tối thiểu. Các bản vá cũng được sử dụng bởi sao chép dựa trên hàng để giảm lượng nhật ký nhị phân được vận chuyển cho nô lệ sao chép, nếu tùy chọn thích hợp được bật. Điều này có thể dẫn đến giảm đáng kể I/O đĩa và I/O mạng cho khối lượng công việc chuyên sâu cập nhật.

Làm thế nào để sử dụng nó

Vậy bạn phải làm gì để có được lợi ích của việc cập nhật một phần các giá trị JSON trong ứng dụng của bạn? Trong nhiều trường hợp không có gì, ngoài việc nâng cấp lên MySQL 8.0. Không có cú pháp mới để cập nhật một phần. Thay vào đó, MySQL phân tích từng câu lệnh cập nhật và cho phép nó có thể, do đó, ứng dụng của bạn sẽ tự động được hưởng lợi từ các cải tiến nếu các câu lệnh cập nhật đã ở trên một biểu mẫu được công nhận là cập nhật một phần.

Một ví dụ đơn giản là câu lệnh sau, thay đổi thuộc tính tên trong giá trị JSON:

UPDATEtSETjson_col=JSON_SET(json_col,'$.name','Knut')WHEREid=123tSETjson_col=JSON_SET(json_col,'$.name','Knut')WHEREid=123

Bản cập nhật này có thể được thực hiện dưới dạng bản cập nhật một phần vì nó lấy cột JSON (JSON_COL), sửa đổi một trong những thành viên của nó và sau đó lưu trữ nó vào cùng một cột như nó đọc từ (json_col). Ngoài ra, giá trị JSON được cập nhật phải có một thành viên được gọi là tên và phải có đủ không gian hiện có trong giá trị JSON để giữ tên mới. Nếu giá trị JSON được cập nhật là một cái gì đó như {"name": "John", ...}, công cụ lưu trữ sẽ được thông báo rằng nó có thể chỉ cần ghi đè bốn byte trong chuỗi Và phần còn lại của giá trị có thể bị bỏ lại.

Nếu giá trị JSON được cập nhật có chứa tên dài hơn, như {"name": "Peter", ...}, bản cập nhật vẫn có thể được thực hiện dưới dạng cập nhật một phần. Trong trường hợp đó, công cụ lưu trữ sẽ được yêu cầu ghi đè bốn byte đầu tiên của Peter Peter, với Kn Knut, và ghi đè lên độ dài của thuộc tính tên với giá trị 4 để khớp với độ dài mới.

Mặt khác, nếu giá trị JSON ban đầu chứa một tên ngắn hơn, như {"Tên": "Joe", ...}, sẽ không có đủ chỗ cho tên mới. Trong trường hợp này, bản cập nhật sẽ quay trở lại để thực hiện bản cập nhật đầy đủ, điều đó có nghĩa là nó viết giá trị JSON hoàn toàn mới vào cơ sở dữ liệu. Tương tự, nếu giá trị JSON ban đầu không có thuộc tính tên, một bản cập nhật đầy đủ sẽ được thực hiện để nhường chỗ cho thuộc tính mới.

Cập nhật một phần không giới hạn trong chức năng json_set. Nó cũng có thể được sử dụng với các hàm json_replace và json_remove. Bạn thậm chí có thể kết hợp các chức năng này, miễn là cột đầu vào giống như cột đích. Và bạn có thể kết hợp cập nhật một phần các cột JSON với các bản cập nhật thông thường của các cột khác trong cùng một câu lệnh. Cả hai câu lệnh cập nhật này sẽ cố gắng cập nhật một phần cột JSON:

UpdatetSet json_col = json_set (json_col, '$. Tên', trên (json_col->> '$. Tên')),tSET json_col=JSON_SET(json_col,'$.name',UPPER(json_col->>'$.name')),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; json_col = json_replace (json_col, '$. tuổi', int_col),json_col=JSON_REPLACE(json_col,'$.age',int_col),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; json_col = json_remove (json_col, '$. địa chỉ'),json_col=JSON_REMOVE(json_col, '$.address'),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; int_col = int_col+1;int_col=int_col+1;

UpdatetSet json_col = json_replace (json_remove (json_col, '$. Địa chỉ'),tSET json_col= JSON_REPLACE(JSON_REMOVE(json_col,'$.address'),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; '$ .name', trên (json_col->> '$. Tên'),'$.name', UPPER(json_col->>'$.name'),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; '$ .age', int_col),'$.age',int_col),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; int_col = int_col+1;int_col=int_col+1;

UpdatetSet json_col = json_replace (json_remove (json_col, '$. Địa chỉ'),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; '$ .name', trên (json_col->> '$. Tên'),

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Createdetablet (idintprimary keyauto_increment,TABLEt(idINTPRIMARY KEYAUTO_INCREMENT,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; json_coljson,json_colJSON,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; NameVarchar (100) là (json_col->> '$. Tên'),nameVARCHAR(100) AS(json_col->>'$.name'),

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; AgeIntas (json_col-> '$. tuổi'));ageINTAS(json_col->'$.age'));

INSERTINTOt(json_col)VALUESINTOt(json_col)VALUES

(JSON_OBJECT('name','Joe','age',24,'name', 'Joe','age',24,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 'dữ liệu', lặp lại ('x', 10*1000*1000)),'data',REPEAT('x',10*1000*1000))),

(JSON_OBJECT('name','Sue','age',32,'name','Sue','age',32,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 'dữ liệu', lặp lại ('y', 10*1000*1000)),'data',REPEAT('y',10*1000*1000))),

(JSON_OBJECT('name','Pete','age',40,'name','Pete','age',40,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 'dữ liệu', lặp lại ('z', 10*1000*1000)),'data',REPEAT('z',10*1000 *1000))),

(JSON_OBJECT('name','Jenny','age',27,'name','Jenny','age',27,

& nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 'Dữ liệu', Lặp lại ('W', 10*1000*1000)));'data',REPEAT('w',10*1000*1000)));

INSERTINTOt(json_col)SELECTjson_colFROMt;INTOt(json_col) SELECTjson_colFROMt;

INSERTINTOt(json_col)SELECTjson_colFROMt;INTOt(json_col)SELECTjson_colFROMt;

Điều này tạo ra một bảng với 16 tài liệu JSON, trong đó mỗi tài liệu khoảng 10MB.

Bây giờ chúng tôi cố gắng tăng thuộc tính tuổi trong mỗi tài liệu với MySQL 5.7:

mysql> updateTetSet json_col = json_set (json_col, '$. tuổi', tuổi+1);>updatetset json_col=json_set(json_col,'$.age',age+1);

Truy vấn OK, bị ảnh hưởng 16Rows (13,56 giây)OK,16 rows affected(13.56sec)

Các hàng phù hợp: 16 & nbsp; & nbsp; đã thay đổi: 16 & nbsp; & nbsp; cảnh báo: 0matched:16  Changed:16  Warnings:0

Nếu chúng tôi thử cùng một câu lệnh cập nhật với MySQL 8.0, chúng tôi sẽ thấy rằng nó nhanh hơn nhiều lần:

mysql> updateTetSet json_col = json_set (json_col, '$. tuổi', tuổi+1);>updatetset json_col=json_set(json_col,'$.age',age+1);

Truy vấn OK, bị ảnh hưởng 16Rows (13,56 giây)OK,16 rows affected(2.94sec)

Các hàng phù hợp: 16 & nbsp; & nbsp; đã thay đổi: 16 & nbsp; & nbsp; cảnh báo: 0matched:16  Changed:16  Warnings:0

Nếu chúng tôi thử cùng một câu lệnh cập nhật với MySQL 8.0, chúng tôi sẽ thấy rằng nó nhanh hơn nhiều lần:

Truy vấn OK, bị ảnh hưởng 16Rows (2,94 giây)>SET binlog_row_value_options=PARTIAL_JSON,binlog_row_image=MINIMAL;

Mặc dù nó nhanh hơn nhiều, nhưng ba giây để cập nhật một vài byte trong 16 tài liệu vẫn không siêu nhanh. Lý do là MySQL 8.0 có ghi nhật ký nhị phân được bật theo mặc định, cũng trong các môi trường không sao chép. Điều này có nghĩa là cả hình ảnh trước và hình ảnh sau của các giá trị JSON lớn được ghi vào nhật ký nhị phân. Như đã đề cập trước đó, một tùy chọn đã được thêm vào để tạo nhật ký nhị phân chứa các bản vá thay vì các tài liệu JSON đầy đủ khi chúng tôi có các bản cập nhật một phần. Hãy để cố gắng kích hoạt tùy chọn đó:OK,0rows affected,1 warning(0.00sec)

mysql> updateTetSet json_col = json_set (json_col, '$. tuổi', tuổi+1);>updatetset json_col=json_set(json_col,'$.age',age+ 1);

Truy vấn OK, bị ảnh hưởng 16Rows (13,56 giây)OK,16rows affected(0.23sec)

Các hàng phù hợp: 16 & nbsp; & nbsp; đã thay đổi: 16 & nbsp; & nbsp; cảnh báo: 0matched:16  Changed:16  Warnings: 0

Nếu chúng tôi thử cùng một câu lệnh cập nhật với MySQL 8.0, chúng tôi sẽ thấy rằng nó nhanh hơn nhiều lần:

Truy vấn OK, bị ảnh hưởng 16Rows (2,94 giây)

Mặc dù nó nhanh hơn nhiều, nhưng ba giây để cập nhật một vài byte trong 16 tài liệu vẫn không siêu nhanh. Lý do là MySQL 8.0 có ghi nhật ký nhị phân được bật theo mặc định, cũng trong các môi trường không sao chép. Điều này có nghĩa là cả hình ảnh trước và hình ảnh sau của các giá trị JSON lớn được ghi vào nhật ký nhị phân. Như đã đề cập trước đó, một tùy chọn đã được thêm vào để tạo nhật ký nhị phân chứa các bản vá thay vì các tài liệu JSON đầy đủ khi chúng tôi có các bản cập nhật một phần. Hãy để cố gắng kích hoạt tùy chọn đó:

mysql> đặt binlog_row_value_options = partial_json, binlog_row_image = tối thiểu;

Truy vấn OK, 0ROWS bị ảnh hưởng, 1Warning (0,00 giây)