Avançar para o conteúdo principal
BlogueBases de dadosAproveitamento das capacidades NoSQL no PostgreSQL

Aproveitando os recursos NoSQL no PostgreSQL

Imagem com um símbolo que representa uma base de dados ligada a outras bases de dados e o texto Harnessing NoSQL Capabilities in PostgreSQL na parte inferior.

Os armazenamentos de documentos NoSQL podem ser ideais para gerir grandes quantidades de dados não estruturados. No entanto, algumas organizações trabalham com dados não estruturados mas continuam a querer as capacidades das bases de dados SQL tradicionais. Por exemplo, as agências de conteúdos mediáticos ou noticiosos podem gerir sítios Web de elevado tráfego centrados em grandes quantidades de conteúdos de texto e imagem. Embora necessitem de armazenar estes dados não estruturados, talvez não precisem realmente dos esquemas flexíveis ou da escalabilidade horizontal das bases de dados NoSQL. Em vez disso, precisam da facilidade de gestão de bases de dados e da consistência de uma base de dados relacional como o PostgreSQL.

É possível obter o melhor dos dois mundos? Sim.

Com seus tipos de dados destinados a suportar dados não estruturados, o PostgreSQL oferece um meio termo, permitindo que você aproveite os recursos NoSQL em um banco de dados relacional que é econômico e simples de gerenciar. Neste artigo, veremos como é possível usar os tipos de dados HStore e JSONB no PostgreSQL para trabalhar com dados não estruturados.

Antes de nos debruçarmos sobre o assunto, vamos analisar brevemente as principais diferenças entre as bases de dados SQL e NoSQL.

Compreender a relação entre SQL e NoSQL

As bases de dados SQL e NoSQL têm os seus pontos fortes e fracos. Tomar uma decisão informada sobre qual delas satisfará melhor as suas necessidades de dados depende de uma forte compreensão das suas diferenças.

As bases de dados SQL (relacionais), como o PostgreSQL e o MySQL, representam dados com uma estrutura clara e previsível em tabelas, linhas e colunas. Aderem às propriedades ACID (atomicidade, consistência, isolamento e durabilidade), que produzem uma base sólida para a integridade dos dados, garantindo que as transacções da base de dados são processadas de forma fiável.

As bases de dados SQL brilham quando a consistência e a integridade dos dados são cruciais, por exemplo, ao lidar com consultas complexas e sistemas transaccionais (como nas aplicações financeiras).

Por outro lado, as bases de dados NoSQL (armazenamentos de documentos) servem para grandes e variados conjuntos de dados que não são necessariamente adequados para representação tabular. Exemplos de bases de dados NoSQL são o MongoDB, o Cassandra e o Couchbase. As bases de dados NoSQL funcionam com esquemas flexíveis, permitindo que as estruturas de dados evoluam ao longo do tempo. Também suportam a escalabilidade horizontal, distribuindo os dados por vários servidores para um melhor tratamento de grandes cargas de dados e tráfego elevado.

As bases de dados NoSQL são frequentemente utilizadas em aplicações em que a escalabilidade é crucial, por exemplo, para tratar grandes quantidades de dados em aplicações em tempo real ou grandes modelos de linguagem (LLM). As bases de dados NoSQL também são benéficas quando se lida com estruturas de dados variadas e em evolução, uma vez que permitem às organizações adaptarem-se à medida que as suas necessidades de dados mudam.

Por que você pode usar o PostgreSQL como um armazenamento de documentos?

O PostgreSQL é uma base de dados relacional, pelo que pode parecer pouco convencional considerá-lo uma opção para satisfazer as necessidades NoSQL. No entanto, a sua situação pode justificar a utilização do PostgreSQL como um armazenamento de documentos.

Se as suas necessidades de armazenamento de dados são diversas - requerendo tanto o armazenamento de dados estruturados e compatíveis com ACID quanto o armazenamento de documentos flexíveis e sem esquema - então você pode aproveitar o PostgreSQL para combinar modelos relacionais e não relacionais. Ou, talvez você queira certos recursos NoSQL, mas também queira as garantias de consistência de dados que vêm com as propriedades ACID. Por fim, como uma tecnologia madura com uma comunidade ativa, o PostgreSQL oferece suporte abrangente a SQL, indexação avançada e pesquisa de texto completo. Esses recursos - combinados com seus recursos NoSQL - fazem do PostgreSQL uma solução versátil de armazenamento de dados.

Limitações do uso do PostgreSQL para dados do tipo NoSQL

Apesar de sua versatilidade, o PostgreSQL tem certas limitações em comparação com os bancos de dados NoSQL tradicionais. Embora o PostgreSQL possa ser escalado verticalmente, ele não suporta inerentemente o escalonamento horizontal ou dados distribuídos com fragmentação automática, recursos que os bancos de dados NoSQL normalmente oferecem. O PostgreSQL também não oferece optimizações para determinadas estruturas de dados NoSQL, como armazenamentos de colunas largas ou bases de dados de grafos. Por fim, o PostgreSQL não oferece consistência ajustável para otimizar o desempenho, o que pode ser obtido em algumas bases de dados NoSQL.

Ao considerar o uso do PostgreSQL para conjuntos de dados grandes e não estruturados, saiba que essas limitações podem afetar o desempenho e sua capacidade de escalonamento. Além disso, a mistura de operações de dados SQL e NoSQL introduz complexidade. O planejamento cuidadoso e a compreensão de ambos os paradigmas o ajudarão a evitar possíveis armadilhas.

No entanto, com o entendimento e o caso de uso corretos, o PostgreSQL pode servir como uma ferramenta poderosa, fornecendo o melhor dos mundos SQL e NoSQL.

HStore e JSONB no PostgreSQL

Ao considerarmos as possibilidades de uso do PostgreSQL como uma solução NoSQL, encontramos três tipos de dados que oferecem funcionalidade semelhante à do NoSQL, mas cada um deles tem características e casos de uso únicos.

  1. Loja: Este tipo de dados permite-lhe armazenar pares chave-valor num único valor PostgreSQL. É útil para armazenar dados semi-estruturados que não têm um esquema fixo.
  2. JSONB: Trata-se de uma representação binária de dados do tipo JSON. Pode armazenar estruturas mais complexas em comparação com o HStore e suporta capacidades JSON completas. O JSONB é indexável, o que o torna uma boa escolha para grandes quantidades de dados.
  3. JSON: É semelhante ao JSONB, embora não tenha muitas das capacidades e eficiências do JSONB. O tipo de dados JSON armazena uma cópia exacta do texto de entrada, que inclui espaço em branco e chaves duplicadas.

Mencionamos o tipo de dados JSON como uma opção válida para armazenar dados formatados em JSON quando não precisar de todos os recursos fornecidos pelo JSONB. No entanto, nosso foco principal para o restante deste artigo será o HStore e o JSONB.

Loja

A documentação do PostgreSQL descreve o HStore como útil quando você tem "linhas com muitos atributos que raramente são examinados, ou dados semi-estruturados". Antes de poder trabalhar com o tipo de dados HStore, certifique-se de habilitar a extensão HStore:

> CREATE EXTENSION hstore;

HStore é representado como zero ou mais chaves => valores separados por vírgulas. A ordem dos pares não é significativa nem é retida de forma fiável na saída.

> SELECT 'foo => bar, prompt => "hello world", pi => 3.14'::hstore;
                      hstore                       
-----------------------------------------------------
"pi"=>"3.14", "foo"=>"bar", "prompt"=>"hello world"
(1 row)

Cada chave HStore é única. Se for efectuada uma declaração HStore com chaves duplicadas, apenas uma das duplicadas será armazenada e não há qualquer garantia sobre qual será essa chave.

> SELECT 'key => value1, key => value2'::hstore;
    hstore     
-----------------
"key"=>"value1"
(1 row)

Com a sua estrutura plana de chave-valor, o HStore oferece simplicidade e rapidez de consulta, tornando-o ideal para cenários simples. No entanto, o HStore apenas suporta dados de texto e não suporta dados aninhados, o que o torna limitado para estruturas de dados complexas.

Por outro lado, o JSONB pode tratar uma maior variedade de tipos de dados.

JSONB

O tipo de dados JSONB aceita texto de entrada formatado em JSON e, em seguida, armazena-o num formato binário decomposto. Embora esta conversão torne a entrada ligeiramente lenta, o resultado é um processamento rápido e uma indexação eficiente. O JSONB não preserva o espaço em branco nem a ordem das chaves dos objectos.

> SELECT '{"foo": "bar", "pi": 3.14, "nested": { "prompt": "hello", "count": 5 } }'::jsonb;
                                jsonb                                
-----------------------------------------------------------------------
{"pi": 3.14, "foo": "bar", "nested": {"count": 5, "prompt": "hello"}}
(1 row)

Se forem fornecidas chaves de objeto duplicadas, é mantido o último valor.

> SELECT '{"key": "value1", "key": "value2"}'::jsonb;
      jsonb      
-------------------
{"key": "value2"}
(1 row)

Como o JSONB suporta estruturas complexas e capacidades JSON completas, é a escolha ideal para dados complexos ou aninhados, preferível ao HStore ou JSON. No entanto, a utilização de JSONB introduz algumas sobrecargas de desempenho e uma maior utilização de armazenamento em comparação com o HStore.

Exemplos práticos: Trabalhar com HStore e JSONB

Vamos considerar alguns exemplos práticos para demonstrar como trabalhar com estes tipos de dados. Iremos analisar a criação de tabelas, consultas e operações básicas e indexação.

Operações básicas do HStore

Como faria com qualquer outro tipo de dados, é possível definir campos na tabela de dados do PostgreSQL como um tipo de dados HStore.

> CREATE TABLE articles (    id serial primary key,    title varchar(64),    meta hstore  );

A inserção de um registo com um atributo HStore tem o seguinte aspeto:

> INSERT INTO articles (title, meta)
  VALUES (
    'Data Types in PostgreSQL',
    'format => blog, length => 1350, language => English, license => "Creative Commons"');

> SELECT * FROM articles;
id |          title           | meta                                     ----+--------------------------+------------------------------------------  1 | Data Types in PostgreSQL | "format"=>"blog", "length"=>"1350", "license"=>"Creative Commons", "language"=>"English"(1 row)

Com os campos HStore, pode ir buscar pares de valores chave específicos ao campo, conforme especificado pelas chaves que fornecer:

> SELECT title,          meta -> 'license' AS license,         meta -> 'format' AS format  FROM articles;
              title              |     license      |   format  
---------------------------------+------------------+------------
Data Types in PostgreSQL        | Creative Commons | blog
Advanced Querying in PostgreSQL | None             | blog
Scaling PostgreSQL              | MIT              | blog
PostgreSQL Fundamentals         | Creative Commons | whitepaper
(4 rows)

Também pode efetuar consultas com critérios baseados em valores específicos num campo HStore.

> SELECT id, title FROM articles WHERE meta -> 'license' = 'Creative Commons';

id |          title          
----+--------------------------
  1 | Data Types in PostgreSQL
  4 | PostgreSQL Fundamentals
(2 rows)

Por vezes, pode querer consultar apenas as linhas que contêm uma chave específica no campo HStore. Por exemplo, a consulta a seguir retorna apenas as linhas em que o meta HStore contém a chave de nota. Para fazer isso, você usaria o operador ?

> SELECT title, meta->'note' AS note FROM articles WHERE meta ? 'note';
              title              |      note      
---------------------------------+-----------------
PostgreSQL Fundamentals         | hold for review
Advanced Querying in PostgreSQL | needs edit
(2 rows)

Uma lista de operadores e funções úteis do HStore pode ser encontrada aqui. Por exemplo, pode extrair as chaves de um HStore para uma matriz, ou pode converter um HStore numa representação JSON.

> SELECT title, akeys(meta) FROM articles where id=1;
          title           |              akeys              
--------------------------+----------------------------------
Data Types in PostgreSQL | {format,length,license,language}
(1 row)

> SELECT title, hstore_to_json(meta) FROM articles where id=1;
          title           |            hstore_to_json
--------------------------+------------------------------------------------
Data Types in PostgreSQL | {"format": "blog", "length": "1350", "license": "Creative Commons", "language": "English"}
(1 row)

Operações básicas de JSONB

Trabalhar com o tipo de dados JSONB no PostgreSQL é simples. A criação de tabelas e a inserção de registos são semelhantes a isto:

> CREATE TABLE authors (id serial primary key, name varchar(64), meta jsonb);

> INSERT INTO authors (name, meta)  VALUES    ('Adam Anderson',     '{ "active":true, "expertise": ["databases", "data science"], "country": "UK" }');

Observe que o meta campo jsonb é fornecido como uma string de texto no formato JSON. O PostgreSQL irá reclamar se o valor fornecido não for um JSON válido.

> INSERT INTO authors (name, meta)  VALUES ('Barbara Brandini', '{ "this is not valid JSON" }');
ERROR:  invalid input syntax for type json

Ao contrário do tipo HStore, o JSONB suporta dados aninhados.

> INSERT INTO authors (name, meta)  VALUES ('Barbara Brandini',          '{ "active":true,             "expertise": ["AI/ML"],             "country": "CAN",             "contact": {               "email": "barbara@example.com",               "phone": "111-222-3333"             }           }');

À semelhança do HStore, os campos JSONB podem ser recuperados parcialmente, apenas com determinadas chaves. Por exemplo:

> SELECT name, meta -> 'country' AS country FROM authors;
      name       | country ------------------+--------- Adam Anderson    | "UK" Barbara Brandini | "CAN" Charles Cooper   | "UK"(3 rows)

O tipo de dados JSONB tem muitos operadores que são semelhantes em utilização ao HStore. Por exemplo, a seguinte utilização do operador ? recupera apenas as linhas em que o campo meta contém a chave de contacto.

> SELECT name,         meta -> 'active' AS active,         meta -> 'contact' AS contact  FROM authors  WHERE meta ? 'contact';
      name       | active |                 contact                         
------------------+--------+-----------------------------------------------
Barbara Brandini | true   | {"email": "barbara@example.com", "phone": "111-222-3333"}
Charles Cooper   | false  | {"email": "charles@example.com"}
(2 rows)

Trabalhar com índices

De acordo com a documentação, o tipo de dados HStore "tem suporte de índice GiST e GIN para os operadores @>, ?, ?& e ?|". Para obter uma explicação detalhada das diferenças entre os dois tipos de índices, consulte aqui. A indexação para JSONB usa índices GIN para facilitar a pesquisa eficiente de chaves ou pares de valores chave.

A instrução para criar um índice é como seria de esperar:

> CREATE INDEX idx_hstore ON articles USING GIN(meta);
> CREATE INDEX idx_jsonb ON authors USING GIN(meta);

Estrutura SQL com flexibilidade NoSQL

Vamos rever o caso de utilização original que mencionámos na introdução. Imaginemos uma agência de conteúdos noticiosos que armazena os seus artigos da mesma forma que um armazenamento de documentos NoSQL. Talvez o artigo possa ser representado em JSON como um conjunto ordenado de objectos que representam secções, cada uma com conteúdo de texto, notações e formatação. Além disso, um conjunto de metadados está associado a cada artigo, e esses atributos de metadados são inconsistentes de um artigo para o outro.

A descrição acima encapsula a maior parte das necessidades de NoSQL da organização, mas tudo o resto sobre a forma como gere e organiza os seus dados está estreitamente alinhado com um modelo de dados relacional.

Combinando as capacidades NoSQL de um tipo de dados como JSONB com os pontos fortes do SQL tradicional do PostgreSQL, a organização pode desfrutar de esquemas flexíveis e consultas rápidas em dados aninhados enquanto ainda é capaz de realizar operações conjuntas e reforçar relacionamentos de dados. Os tipos de dados HStore e JSONB do PostgreSQL oferecem opções poderosas para desenvolvedores que precisam da estrutura de um banco de dados relacional, mas também precisam de armazenamento de dados no estilo NoSQL.

PostgreSQL em escala

Está a tentar suportar o armazenamento e a consulta de dados ao estilo NoSQL, mantendo-se dentro da estrutura de uma base de dados relacional tradicional? Talvez a sua organização lide com documentos de forma semelhante à que descrevemos neste post. Ou talvez esteja à procura de opções para lidar com o armazenamento de dados não estruturados para um modelo de linguagem grande (LLM) ou outro empreendimento de IA/ML.

O PostgreSQL Cluster no Linode Marketplace oferece o modelo relacional e a estrutura de um banco de dados SQL, juntamente com a escalabilidade horizontal de um banco de dados NoSQL. Combine isso com o uso de tipos de dados HStore ou JSONB e terá uma solução híbrida ideal para aproveitar os recursos NoSQL enquanto trabalha no PostgreSQL.

Comentários

Deixe uma resposta

O seu endereço de correio electrónico não será publicado. Os campos obrigatórios estão marcados com *