Na indústria de jogos, o código da aplicação geralmente serializa dados usando Protobuf — às vezes com compressão zlib adicional — e os grava em colunas BLOB. Ler esses dados via SQL normalmente exige componentes externos de ETL ou desserialização na camada da aplicação, o que dificulta a depuração e o desenvolvimento de software. O recurso de Protobuf legível do PolarDB for MySQL elimina ambas as necessidades. Use a função PROTO_TO_JSON() para converter dados BLOB em JSON diretamente na consulta e utilize as funções JSON padrão do MySQL (JSON_EXTRACT(), JSON_UNQUOTE()) para filtrar, indexar ou criar colunas virtuais sobre esses dados — tudo em SQL.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster PolarDB for MySQL 8.0 executando a versão de revisão 8.0.2.2.5 ou posterior. Para verificar sua versão, consulte Consultar a versão do mecanismo.
Como funciona
A função PROTO_TO_JSON(blob_field) recebe uma coluna BLOB com dados serializados em Protobuf e retorna uma string JSON. Ela processa automaticamente bytes Protobuf brutos e comprimidos com zlib, sem necessidade de alterar a consulta entre os dois casos.
Após converter os dados BLOB para JSON, use as funções JSON padrão do MySQL para consultar campos, criar índices ou gerar colunas virtuais sobre os dados Protobuf.
Configurar um schema Protobuf para uma coluna
Antes de chamar PROTO_TO_JSON(), associe um schema Protobuf à coluna BLOB usando ALTER TABLE ... ALTER COLUMN. Essa etapa define como o PolarDB for MySQL interpreta os dados binários nessa coluna.
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:
|
Parâmetro |
Obrigatório |
Descrição |
|
|
Não |
Nome do schema Protobuf. |
|
|
Sim |
Definição completa do schema Protobuf. |
|
|
Sim |
Tipo de mensagem Protobuf de nível superior a desserializar. |
|
|
Não |
Defina como |
Também é possível descomprimir manualmente dados com zlib usando UNCOMPRESS() , que retorna os bytes brutos em hexadecimal.
Remover um schema Protobuf de uma coluna
Para remover o schema, defina todos os parâmetros correspondentes como strings vazias:
ALTER TABLE table_name ALTER COLUMN column_name
PROTO_NAME=""
PROTO_TEXT=""
PROTO_MESSAGE='';
Antes de remover o schema, certifique-se de que nenhum índice ou coluna virtual referencie a coluna.
Visualizar o schema Protobuf de uma coluna
-
Ative a exibição do schema para a sessão:
SET display_readable_proto_info = true; -
Exiba as definições das colunas:
SHOW columns FROM table_name;
Exemplos
Os exemplos a seguir usam o schema addressbook.proto da comunidade Protobuf para demonstrar um fluxo de trabalho completo: criação de tabela, configuração de schema, inserção de dados e consulta.
Schema usado em todos os exemplos:
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;
}
Etapa 1: Criar a tabela
CREATE TABLE t1 (c1 INT, c2 BLOB);
A coluna c2 armazena dados serializados em Protobuf.
Etapa 2: Associar o schema à coluna
Escolha a instrução adequada ao tipo de compressão dos seus dados.
Sem compressão 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';
Com compressão 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';
Etapa 3: Inserir dados
Sem compressão zlib:
INSERT INTO t1 VALUES(1, X'0a380a0b56697375616c50726f746f10011a1776697375616c70726f746f40706f6c617264622e636f6d220e0a0a313233343536373839301002');
Com compressão zlib:
INSERT INTO t1 VALUES(1, X'3C000000785ee3b2e0e20ecb2c2e4dcc0928ca2fc9176094122f03730b405c8782fc9cc4a29424bde4fc5c253e2e2e432363135333730b4b03012600183d10de');
Para verificar os bytes comprimidos, descomprima-os com UNCOMPRESS():
SELECT HEX(UNCOMPRESS(X'3C000000785ee3b2e0e20ecb2c2e4dcc0928ca2fc9176094122f03730b405c8782fc9cc4a29424bde4fc5c253e2e2e432363135333730b4b03012600183d10de')) AS UNCOMPRESS_DATA;
Resultado:
+----------------------------------------------------------------------------------------------------------------------+
| UNCOMPRESS_DATA |
+----------------------------------------------------------------------------------------------------------------------+
| 0A380A0B56697375616C50726F746F10011A1776697375616C70726F746F40706F6C617264622E636F6D220E0A0A313233343536373839301002 |
+----------------------------------------------------------------------------------------------------------------------+
Etapa 4: Ler e consultar os dados
Ler dados BLOB sem PROTO_TO_JSON()
Sem o recurso de Protobuf legível, consultar diretamente a coluna c2 retorna dados binários ilegíveis:
Sem compressão zlib:
SELECT c2 FROM t1\G
Resultado:
*************************** 1. row ***************************
c2:
8
VisualProtovisualproto@polardb.com"
1234567890
Com compressão zlib:
SELECT c2 FROM t1\G
Resultado:
*************************** 1. row ***************************
c2: < x^...
A saída comprimida consiste em dados binários ilegíveis.
Ler dados BLOB como JSON
A função PROTO_TO_JSON() funciona tanto para dados comprimidos quanto não comprimidos, sem exigir alterações na consulta:
SELECT PROTO_TO_JSON(c2) FROM t1;
Resultado:
+------------------------------------------------------------------------------------------------------------------------------------------+
| PROTO_TO_JSON(c2) |
+------------------------------------------------------------------------------------------------------------------------------------------+
| {"people": [{"id": 1, "name": "VisualProto", "email": "visualproto@polardb.com", "phones": [{"type": "WORK", "number": "1234567890"}]}]} |
+------------------------------------------------------------------------------------------------------------------------------------------+
A função PROTO_TO_JSON() lê dados comprimidos com zlib e não comprimidos.
Extrair um campo específico
Use JSON_EXTRACT() para obter campos individuais da saída JSON:
SELECT JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].name') FROM t1;
Resultado:
+-----------------------------------------------------+
| json_extract(PROTO_TO_JSON(c2), '$.people[0].name') |
+-----------------------------------------------------+
| "VisualProto" |
+-----------------------------------------------------+
Criar um índice em um campo Protobuf
Crie um índice funcional no campo de e-mail:
CREATE INDEX i_email ON t1 ((CAST(JSON_UNQUOTE(JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].email')) AS CHAR(100))));
Verifique o uso do índice executando EXPLAIN:
EXPLAIN SELECT * FROM t1 WHERE CAST(JSON_UNQUOTE(JSON_EXTRACT(PROTO_TO_JSON(c2), '$.people[0].email')) AS CHAR(100)) = 'visualproto@polardb.com';
Resultado:
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| 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 |
+----+-------------+-------+------------+------+---------------+---------+---------+-------+------+----------+-------+
Criar uma coluna virtual
Gere uma coluna virtual que exponha um campo Protobuf como coluna regular:
ALTER TABLE t1 ADD COLUMN c3 VARCHAR(100) AS (JSON_EXTRACT(PROTO_TO_JSON(`c2`), _utf8mb4'$.people[0].email'));
Verifique o schema:
DESC t1;
Resultado:
+-------+--------------+------+-----+---------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------------------+
| c1 | int(11) | YES | | NULL | |
| c2 | blob | YES | | NULL | |
| c3 | varchar(100) | YES | | NULL | VIRTUAL GENERATED |
+-------+--------------+------+-----+---------+-------------------+
A coluna c3 é uma coluna virtual gerada com base nos dados Protobuf em c2.