All Products
Search
Document Center

PolarDB:Readable Protobuf

Last Updated:Mar 29, 2026

Di industri game, aplikasi umumnya melakukan serialisasi data menggunakan Protobuf—kadang-kadang dengan kompresi zlib tambahan—lalu menyimpannya ke dalam kolom BLOB. Membaca data tersebut melalui SQL biasanya memerlukan komponen ETL eksternal atau deserialisasi di lapisan aplikasi, yang tidak praktis untuk debugging dan pengembangan perangkat lunak. Fitur readable Protobuf di PolarDB for MySQL menghilangkan kedua kebutuhan tersebut. Gunakan fungsi PROTO_TO_JSON() untuk mengonversi data BLOB menjadi JSON secara inline, lalu gunakan fungsi JSON standar MySQL (JSON_EXTRACT(), JSON_UNQUOTE()) untuk menyaring, membuat indeks, atau membuat kolom virtual berdasarkan data tersebut—semuanya dilakukan langsung dalam SQL.

Prasyarat

Sebelum memulai, pastikan Anda memiliki:

  • Kluster PolarDB for MySQL 8.0 yang menjalankan versi revisi 8.0.2.2.5 atau lebih baru. Untuk memeriksa versi Anda, lihat Kueri versi engine.

Cara kerja

PROTO_TO_JSON(blob_field) menerima kolom BLOB yang berisi data Protobuf ter-serialisasi dan mengembalikan string JSON. Fungsi ini secara otomatis menangani byte Protobuf mentah maupun byte Protobuf yang dikompresi zlib—tidak diperlukan perubahan pada kueri Anda untuk kedua kasus tersebut.

Setelah mengonversi data BLOB ke JSON, gunakan fungsi JSON standar MySQL untuk mengkueri bidang, membuat indeks, atau menghasilkan kolom virtual berdasarkan data Protobuf.

Konfigurasikan skema Protobuf untuk suatu kolom

Sebelum memanggil PROTO_TO_JSON(), kaitkan skema Protobuf dengan kolom BLOB menggunakan ALTER TABLE ... ALTER COLUMN. Langkah ini memberi tahu PolarDB for MySQL cara menginterpretasikan data biner dalam kolom tersebut.

Syntax:

ALTER TABLE table_name ALTER COLUMN column_name
  [PROTO_NAME = 'protobuf_schema_name']
  PROTO_TEXT = 'protobuf_schema_definition'
  PROTO_MESSAGE = 'protobuf_message'
  [COMPRESSION = 'zlib']

Parameters:

ParameterWajibDeskripsi
PROTO_NAMETidakNama untuk skema Protobuf.
PROTO_TEXTYaDefinisi lengkap skema Protobuf.
PROTO_MESSAGEYaJenis pesan Protobuf tingkat atas yang akan dideserialisasi.
COMPRESSIONTidakAtur ke zlib jika data dikompresi dengan zlib sebelum ditulis ke kolom. Abaikan parameter ini untuk data yang tidak terkompresi.
Data yang dikompresi zlib juga dapat didekompresi secara manual menggunakan UNCOMPRESS(), yang mengembalikan byte mentah dalam bentuk heksadesimal.

Hapus skema Protobuf dari suatu kolom

Untuk menghapus skema, atur semua parameter skema ke string kosong:

ALTER TABLE table_name ALTER COLUMN column_name
  PROTO_NAME=""
  PROTO_TEXT=""
  PROTO_MESSAGE='';
Penting

Sebelum menghapus skema, pastikan kolom tersebut tidak lagi dirujuk oleh indeks atau kolom virtual apa pun.

Lihat skema Protobuf untuk suatu kolom

  1. Aktifkan tampilan skema untuk sesi:

    SET display_readable_proto_info = true;
  2. Tampilkan definisi kolom:

    SHOW columns FROM table_name;

Contoh

Contoh berikut menggunakan skema addressbook.proto dari komunitas Protobuf untuk menjelaskan alur kerja lengkap: membuat tabel, mengonfigurasi skema, memasukkan data, dan mengkuerinya.

Skema yang digunakan dalam semua contoh:

syntax = "proto2";

package tutorial;

message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    optional string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

Langkah 1: Buat tabel

CREATE TABLE t1 (c1 INT, c2 BLOB);

c2 berisi data Protobuf ter-serialisasi.

Langkah 2: Kaitkan skema ke kolom

Pilih pernyataan yang sesuai dengan apakah data Anda dikompresi atau tidak.

Tanpa kompresi zlib:

ALTER TABLE t1 ALTER COLUMN c2
  PROTO_NAME="AddressBook"
  PROTO_TEXT="syntax = \"proto2\";\n\npackage tutorial;\n\nmessage Person {\n  optional string name = 1;\n  optional int32 id = 2;\n  optional string email = 3;\n\n  enum PhoneType {\n    MOBILE = 0;\n    HOME = 1;\n    WORK = 2;\n  }\n\n  message PhoneNumber {\n    optional string number = 1;\n    optional PhoneType type = 2 [default = HOME];\n  }\n\n  repeated PhoneNumber phones = 4;\n}\n\nmessage AddressBook {\n  repeated Person people = 1;\n}"
  PROTO_MESSAGE='AddressBook';

Dengan kompresi zlib:

ALTER TABLE t1 ALTER COLUMN c2
  PROTO_NAME="AddressBook"
  PROTO_TEXT="syntax = \"proto2\";\n\npackage tutorial;\n\nmessage Person {\n  optional string name = 1;\n  optional int32 id = 2;\n  optional string email = 3;\n\n  enum PhoneType {\n    MOBILE = 0;\n    HOME = 1;\n    WORK = 2;\n  }\n\n  message PhoneNumber {\n    optional string number = 1;\n    optional PhoneType type = 2 [default = HOME];\n  }\n\n  repeated PhoneNumber phones = 4;\n}\n\nmessage AddressBook {\n  repeated Person people = 1;\n}"
  PROTO_MESSAGE='AddressBook'
  COMPRESSION='zlib';

Langkah 3: Masukkan data

Tanpa kompresi zlib:

INSERT INTO t1 VALUES(1, X'0a380a0b56697375616c50726f746f10011a1776697375616c70726f746f40706f6c617264622e636f6d220e0a0a313233343536373839301002');

Dengan kompresi zlib:

INSERT INTO t1 VALUES(1, X'3C000000785ee3b2e0e20ecb2c2e4dcc0928ca2fc9176094122f03730b405c8782fc9cc4a29424bde4fc5c253e2e2e432363135333730b4b03012600183d10de');

Untuk memverifikasi byte terkompresi, dekompresi menggunakan UNCOMPRESS():

SELECT HEX(UNCOMPRESS(X'3C000000785ee3b2e0e20ecb2c2e4dcc0928ca2fc9176094122f03730b405c8782fc9cc4a29424bde4fc5c253e2e2e432363135333730b4b03012600183d10de')) AS UNCOMPRESS_DATA;

Hasil:

+----------------------------------------------------------------------------------------------------------------------+
| UNCOMPRESS_DATA                                                                                                      |
+----------------------------------------------------------------------------------------------------------------------+
| 0A380A0B56697375616C50726F746F10011A1776697375616C70726F746F40706F6C617264622E636F6D220E0A0A313233343536373839301002 |
+----------------------------------------------------------------------------------------------------------------------+

Langkah 4: Baca dan kueri data

Baca data BLOB tanpa PROTO_TO_JSON()

Tanpa fitur readable Protobuf, mengkueri kolom c2 secara langsung mengembalikan data biner yang tidak dapat diinterpretasikan:

Tanpa kompresi zlib:

SELECT c2 FROM t1\G

Hasil:

*************************** 1. row ***************************
c2:
8
VisualProtovisualproto@polardb.com"
1234567890

Dengan kompresi zlib:

SELECT c2 FROM t1\G

Hasil:

*************************** 1. row ***************************
c2: <   x^...

Output terkompresi berupa sampah biner yang tidak dapat dibaca secara langsung.

Baca data BLOB sebagai JSON

PROTO_TO_JSON() berfungsi baik untuk data terkompresi maupun tidak terkompresi—tidak diperlukan perubahan pada kueri Anda:

SELECT PROTO_TO_JSON(c2) FROM t1;

Hasil:

+------------------------------------------------------------------------------------------------------------------------------------------+
| PROTO_TO_JSON(c2)                                                                                                                        |
+------------------------------------------------------------------------------------------------------------------------------------------+
| {"people": [{"id": 1, "name": "VisualProto", "email": "visualproto@polardb.com", "phones": [{"type": "WORK", "number": "1234567890"}]}]} |
+------------------------------------------------------------------------------------------------------------------------------------------+
PROTO_TO_JSON() dapat membaca data baik yang dikompresi zlib maupun yang tidak terkompresi.

Ekstrak bidang tertentu

Gunakan JSON_EXTRACT() untuk mengambil bidang individual dari output JSON:

SELECT JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].name') FROM t1;

Hasil:

+-----------------------------------------------------+
| json_extract(PROTO_TO_JSON(c2), '$.people[0].name') |
+-----------------------------------------------------+
| "VisualProto"                                       |
+-----------------------------------------------------+

Buat indeks pada bidang Protobuf

Buat indeks fungsional pada bidang email:

CREATE INDEX i_email ON t1 ((CAST(JSON_UNQUOTE(JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].email')) AS CHAR(100))));

Verifikasi bahwa indeks digunakan dengan menjalankan EXPLAIN:

EXPLAIN SELECT * FROM t1 WHERE CAST(JSON_UNQUOTE(JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].email')) AS CHAR(100)) = 'visualproto@polardb.com';

Hasil:

+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t1    | NULL       | ref  | i_email       | i_email | 403     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+

Buat kolom virtual

Buat kolom virtual yang mengekspos bidang Protobuf sebagai kolom biasa:

ALTER TABLE t1 ADD COLUMN c3 VARCHAR(100) AS (JSON_EXTRACT(PROTO_TO_JSON(`c2`), _utf8mb4'$.people[0].email'));

Verifikasi skema:

DESC t1;

Hasil:

+-------+--------------+------+-----+---------+-------------------+
| Field | Type         | Null | Key | Default | Extra             |
+-------+--------------+------+-----+---------+-------------------+
| c1    | int(11)      | YES  |     | NULL    |                   |
| c2    | blob         | YES  |     | NULL    |                   |
| c3    | varchar(100) | YES  |     | NULL    | VIRTUAL GENERATED |
+-------+--------------+------+-----+---------+-------------------+

c3 adalah kolom virtual yang di-generate berdasarkan data Protobuf di c2.