{"id":7351,"date":"2019-08-06T06:57:07","date_gmt":"2019-08-06T13:57:07","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=7351"},"modified":"2023-07-26T12:09:43","modified_gmt":"2023-07-26T19:09:43","slug":"postgres-jsonb-and-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/postgres-jsonb-and-nosql\/","title":{"rendered":"Compara\u00e7\u00e3o do Postgres JSONB com o NoSQL"},"content":{"rendered":"<p><span style=\"font-weight: 400\">A realidade \u00e9 que os bancos de dados est\u00e3o convergindo e, nos \u00faltimos anos, est\u00e1 se tornando cada vez mais dif\u00edcil apontar quais s\u00e3o os melhores cen\u00e1rios para cada armazenamento de dados sem uma compreens\u00e3o profunda de como as coisas funcionam nos bastidores.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">O Postgres tem sido meu RDBMS favorito h\u00e1 anos, e estou entusiasmado com a crescente popularidade de seu suporte a JSONB. Na minha opini\u00e3o, isso ajudar\u00e1 os desenvolvedores a se familiarizarem mais com todas as vantagens de armazenar dados como JSON em vez de tabelas antigas.<\/span><\/p>\n<p><span style=\"font-weight: 400\">No entanto, j\u00e1 vi muitas pessoas apresentarem inadvertidamente o Postgres 11 como \"O novo NoSQL\" ou que n\u00e3o precisam de nenhum <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/resources\/why-nosql\/\">Banco de dados NoSQL<\/a> pois j\u00e1 est\u00e3o usando o Postgres. Neste artigo, gostaria de abordar as principais diferen\u00e7as e os casos de uso.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Se voc\u00ea n\u00e3o tiver tempo para ler o artigo inteiro, resumirei as descobertas mais importantes na conclus\u00e3o.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Modelagem de dados: RDBMS e bancos de dados de documentos<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Todos n\u00f3s conhecemos o custo de uma opera\u00e7\u00e3o JOIN em um RDBMS em escala: Se voc\u00ea tiver 1 milh\u00e3o de usu\u00e1rios com 10 prefer\u00eancias cada, ent\u00e3o, para trazer esse usu\u00e1rio de volta \u00e0 mem\u00f3ria, supondo que voc\u00ea esteja usando uma estrutura ORM (<\/span><span style=\"font-weight: 400\">Mapeamento objeto-relacional<\/span><span style=\"font-weight: 400\">), voc\u00ea precisar\u00e1 fazer uma jun\u00e7\u00e3o com uma tabela de USER_PREFERENCES com 10 milh\u00f5es de linhas.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Em um cen\u00e1rio do mundo real, os usu\u00e1rios geralmente tamb\u00e9m est\u00e3o associados a muitas outras entidades, o que tornar\u00e1 esse cen\u00e1rio ainda pior e for\u00e7ar\u00e1 os desenvolvedores a decidir quais relacionamentos devem ser pregui\u00e7osos ou ansiosos. Atualmente, todos os RDBMS j\u00e1 t\u00eam muitas otimiza\u00e7\u00f5es para o cen\u00e1rio acima, mas modelar os dados da forma como temos feito nos \u00faltimos 30 anos definitivamente n\u00e3o \u00e9 o ideal.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Um dos motivos pelos quais o RDBMS se tornou t\u00e3o bom em lidar com transa\u00e7\u00f5es \u00e9 exatamente a limita\u00e7\u00e3o de seu modelo de dados: Faz sentido armazenar um pedido se n\u00e3o houver itens nele? Ainda assim, sou obrigado a criar uma transa\u00e7\u00e3o para salvar essa \"unidade \u00fanica\" espalhada entre pelo menos duas tabelas: <\/span><b>ORDEM<\/b><span style=\"font-weight: 400\"> e <\/span><b>ORDER_ITEM<\/b><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Vejamos um cen\u00e1rio ainda mais comum: como um usu\u00e1rio pode ser armazenado em um banco de dados de documentos em compara\u00e7\u00e3o com um RDBMS:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7381\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p1-1-1024x523.png\" alt=\"\" width=\"900\" height=\"460\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-1024x523.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-300x153.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-768x392.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1-20x10.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p1-1.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Em um banco de dados de documentos, as entidades com relacionamentos fortes geralmente s\u00e3o armazenadas em uma \u00fanica estrutura. Nessa abordagem, quase n\u00e3o h\u00e1 custo adicional para carregar itens como prefer\u00eancias e permiss\u00f5es, enquanto em um modelo relacional isso exigiria pelo menos duas uni\u00f5es.<\/span><\/p>\n<p><span style=\"font-weight: 400\">\u00a0Agora, vamos expandir esse exemplo para um caso de uso simples de com\u00e9rcio eletr\u00f4nico:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7353\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p2-1024x658.png\" alt=\"\" width=\"739\" height=\"475\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-1024x658.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-300x193.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-768x493.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2-20x13.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p2.png 1177w\" sizes=\"auto, (max-width: 739px) 100vw, 739px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">No exemplo acima, um banco de dados de documentos n\u00e3o precisaria de nenhum JOIN para listar usu\u00e1rios e produtos. No entanto, para os pedidos, ele pode precisar de um ou dois, o que \u00e9 totalmente aceit\u00e1vel. O mesmo modelo em um RDBMS exigiria pelo menos cerca de 12 tabelas:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7354\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p3-1024x910.png\" alt=\"\" width=\"598\" height=\"531\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-1024x910.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-300x267.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-768x683.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3-20x18.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p3.png 1052w\" sizes=\"auto, (max-width: 598px) 100vw, 598px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Usando nosso exemplo acima, voc\u00ea pode notar que os JOINs s\u00e3o essenciais para um RDBMS, enquanto no banco de dados de documentos eles s\u00e3o usados com menos frequ\u00eancia. O mesmo se aplica a transa\u00e7\u00f5es ou opera\u00e7\u00f5es em cascata, pois a maioria das entidades relacionadas \u00e9 armazenada em um \u00fanico documento.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Alguns dos bancos de dados NoSQL mais famosos do mercado ainda n\u00e3o oferecem suporte adequado a JOINs. Felizmente, esse n\u00e3o \u00e9 o caso aqui. O Couchbase suporta at\u00e9 mesmo <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/pt\/ansi-join-support-n1ql\/\"><span style=\"font-weight: 400\">ANSI JOINs<\/span><\/a><span style=\"font-weight: 400\">:\u00a0<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">SELECT DISTINCT route.destinationairportFROM `travel-sample` airport JOIN `travel-sample` route\u00a0 \r\n     ON airport.faa = route.sourceairport\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       AND route.type = \"route\"\r\nWHERE airport.type = \"airport\"\u00a0\u00a0\r\n     AND airport.city = \"San Francisco\"\u00a0\u00a0\r\n     AND airport.country = \"United States\";<\/pre>\n<p><span style=\"font-weight: 400\">Sei que voc\u00ea j\u00e1 deve ter visto essa explica\u00e7\u00e3o sobre a modelagem de dados para RDBMS e a modelagem de dados para NoSQL, mas preciso enfatizar isso, pois cada banco de dados \u00e9 otimizado para um modelo de dados espec\u00edfico, e isso ter\u00e1 um papel importante durante os testes de desempenho.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>O mito do silo<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Como o usu\u00e1rio e o nome do produto raramente ser\u00e3o alterados, voc\u00ea poderia simplesmente armazen\u00e1-los na entidade Orders para evitar alguns JOINS. <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/products\/capella\/\">Bancos de dados NoSQL<\/a>mas isso n\u00e3o \u00e9 rigorosamente aplicado:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-7355\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p4-1024x476.png\" alt=\"\" width=\"512\" height=\"238\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-1024x476.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-300x139.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-768x357.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4-20x9.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p4.png 1143w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/p>\n<p><span style=\"font-weight: 400\">O armazenamento em cache de dados em outras entidades pode melhorar significativamente o desempenho da consulta em escala, mas h\u00e1 algumas compensa\u00e7\u00f5es: Se voc\u00ea tiver que armazenar em cache esses dados em v\u00e1rias partes do sistema, sempre que esses dados forem alterados, ser\u00e1 necess\u00e1rio executar algumas atualiza\u00e7\u00f5es para \"manter os dados sincronizados\".\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">J\u00e1 vi muitos desenvolvedores experientes usarem isso como uma desvantagem dos bancos de dados de documentos, e sempre tenho que lembr\u00e1-los de que voc\u00ea poderia ter exatamente o mesmo problema em um RDBMS.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Tipo de coluna JSONB do Postgres<\/b><\/h2>\n<p><span style=\"font-weight: 400\">No Postgres, JSONB \u00e9 um tipo especial de coluna que pode armazenar JSON em um formato otimizado para leituras:<\/span><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE TABLE my_table (\u00a0\u00a0id integer NOT NULL,\u00a0\u00a0data jsonb);<\/pre>\n<p><span style=\"font-weight: 400\">Conforme declarado neste <\/span><a href=\"https:\/\/www.youtube.com\/watch?v=tMT16q9pqp\"><span style=\"font-weight: 400\">v\u00eddeo<\/span><\/a><span style=\"font-weight: 400\">Embora haja algumas penalidades de desempenho ao armazenar dados em uma coluna JSONB, o banco de dados precisa analisar o JSON para armazen\u00e1-lo em um formato otimizado para leituras, o que parece ser uma compensa\u00e7\u00e3o justa.<\/span><\/p>\n<p><b>OBSERVA\u00c7\u00c3O:<\/b><span style=\"font-weight: 400\"> Vamos ignorar a coluna JSON do Postgres por enquanto, pois at\u00e9 mesmo o documento do Postgres afirma que voc\u00ea deve, em geral, escolher JSONB em vez do tipo de coluna JSON.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Em teoria, voc\u00ea pode at\u00e9 emular um banco de dados de documentos no Postgres usando uma coluna JSONB para todas as entidades aninhadas:<\/span><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE TABLE users (\u00a0\u00a0\r\n     id integer NOT NULL,\u00a0\u00a0\r\n     name varchar,\u00a0\u00a0username varchar,\u00a0\u00a0\r\n     address jsonb,\u00a0\u00a0\r\n     preferences jsonb,\u00a0\u00a0\r\n     permissions jsonb\r\n);<\/pre>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Manipula\u00e7\u00e3o de dados<\/span><\/h2>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">\u00c9 aqui que as coisas come\u00e7am a ficar realmente interessantes: Em primeiro lugar, o Postgres n\u00e3o est\u00e1 seguindo exatamente o padr\u00e3o <\/span><a href=\"https:\/\/standards.iso.org\/ittf\/PubliclyAvailableStandards\/c067367_ISO_IEC_TR_19075-6_2017.zip\"><span style=\"font-weight: 400\">Padr\u00f5es SQL:2016<\/span><\/a><span style=\"font-weight: 400\"> (<\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/ISO_9075\"><b>ISO\/IEC 9075:2016<\/b><\/a><span style=\"font-weight: 400\">). Isso n\u00e3o \u00e9 necessariamente uma coisa ruim, pois as consultas nessa especifica\u00e7\u00e3o podem facilmente ficar muito grandes, mas ainda assim \u00e9 algo a se ter em mente.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Eu sempre gosto de destacar os padr\u00f5es porque os bancos de dados NoSQL j\u00e1 passaram por esse caminho antes, e hoje temos dezenas de linguagens diferentes e um investimento significativo em refatora\u00e7\u00e3o se voc\u00ea quiser migrar de um NoSQL para outro.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Espero que sim, <\/span><a href=\"https:\/\/forward.ucsd.edu\/sqlpp.html\"><span style=\"font-weight: 400\">SQL++<\/span><\/a><span style=\"font-weight: 400\"> veio em seu socorro, o pai do pr\u00f3prio SQL, Don Chamberlin, <\/span><a href=\"https:\/\/www.amazon.com\/SQL-Users-Tutorial-Don-Chamberlin\/dp\/0692184503\"><span style=\"font-weight: 400\">escreveu um livro sobre isso<\/span><\/a><span style=\"font-weight: 400\"> no ano passado. Nesta sess\u00e3o, compararei as fun\u00e7\u00f5es e os operadores JSON do Postgress com uma implementa\u00e7\u00e3o do SQL++ chamada N1QL, que \u00e9 a linguagem de consulta que usamos no Couchbase.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Inser\u00e7\u00f5es<\/span><\/h3>\n<p><span style=\"font-weight: 400\">As inser\u00e7\u00f5es s\u00e3o o que voc\u00ea espera, a principal diferen\u00e7a entre a sintaxe do Postgres e a do N1QL \u00e9 que, no primeiro, apenas algumas colunas de uma linha conter\u00e3o strings codificadas em JSON, enquanto no segundo, todo o documento \u00e9 um JSON:<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">INSERT INTO users VALUES (1, 'First User', 'user1',\u00a0\u00a0 \r\n'{\"streetName\": \"Wayside Lane\", \"houseNumber\": 3104, \"zipcode\": \"94538\", \"city\": \"Fremont\", \"state\": \"CA\", \"country\": \"US\", \"entrances\": [{\"name\" : \"main\"}] }',\u00a0\u00a0\r\n'[{\"name\": \"lang\", \"value\": \"en\"},{\"name\": \"notification\", \"value\":\"emailOnly\"},\u00a0{{\"name\":\"timezone\",\"value\": \"GMT+2\"}]',\u00a0\r\n'{\"groups\":[\"MARKETING\"], \"roles\": [\"ADMIN\", \"PREMIUM_USER\"]}');<\/pre>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">INSERT INTO `test` ( KEY, VALUE ) VALUES ( \"1\", {\r\n  \"type\": \"users\",\r\n  \"name\": \"First User\",\r\n  \"username\": \"user1\",\r\n  \"address\": {\r\n    \"streetName\": \"Wayside Lane\", \r\n      \"houseNumber\": 3104, \r\n        \"zipcode\": 94538, \r\n        \"city\": \"Fremont\", \r\n        \"state\": \"CA\", \r\n        \"country\": \"US\", \r\n        \"entrances\": [{\"name\" : \"main\"}] },\r\n  \"preferences\": [\r\n    {\"name\": \"lang\", \"value\": \"en\"},\r\n    {\"name\": \"notification\", \"value\":\"emailOnly\"},\r\n    {\"name\":\"timezone\",\"value\": \"GMT+2\"}],\r\n  \"permissions\": {\r\n    \"groups\":[\"MARKETING\"], \r\n    \"roles\": [\"ADMIN\", \"PREMIUM_USER\"]}\r\n});\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Atualiza\u00e7\u00f5es<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Vamos come\u00e7ar com uma atualiza\u00e7\u00e3o muito simples<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">update users set address = jsonb_set(address, '{state}', '\"California\"') WHERE address-&gt;'state' = '\"CA\"';<\/pre>\n<p><span style=\"font-weight: 400\">Na sintaxe do Postgres, as cadeias de caracteres devem ser especificadas entre aspas duplas e simples ('\"CA\"'), enquanto os literais devem estar entre aspas simples (\"false\" ou \"123\").\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">update `test` set address.state = 'California' where address.state = 'CA' and type = 'users'<\/pre>\n<p><span style=\"font-weight: 400\">No Couchbase, n\u00e3o h\u00e1 um conceito semelhante a uma tabela, portanto, diferenciamos os documentos de acordo com um \"<\/span><b>tipo<\/b><span style=\"font-weight: 400\">\", que, nesse caso, deve ser igual a \"<\/span><b>usu\u00e1rios<\/b><span style=\"font-weight: 400\">\". Todo o restante da consulta \u00e9 semelhante ao SQL padr\u00e3o ou, se voc\u00ea veio do mundo Java, \u00e9 quase a mesma sintaxe do JPA JPQL.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Vamos tentar um exemplo mais complexo em que adicionamos uma nova entrada \u00e0 casa, atualizamos o c\u00f3digo postal e removemos a fun\u00e7\u00e3o ADMIN do usu\u00e1rio de destino:<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">UPDATE users\r\n   SET address = jsonb_set( jsonb_set(\r\n\t\t\t\t\taddress::jsonb,\r\n\t\t\t\t\tarray['entrances'],\r\n\t\t\t\t\t(address-&gt;'entrances')::jsonb || '{\"name\": \"backyard\"}'::jsonb), \r\n\t\t\t\t '{zipcode}', '94537'),\r\n\t\tpermissions = jsonb_set(permissions, '{roles}', (permissions-&gt;'roles') - 'ADMIN')<\/pre>\n<p><span style=\"font-weight: 400\">As consultas do Postgres podem facilmente se tornar muito complexas se voc\u00ea precisar manipular o JSON. Em alguns casos, voc\u00ea pode at\u00e9 mesmo <\/span><a href=\"https:\/\/stackoverflow.com\/questions\/45035597\/how-to-update-deeply-nested-json-object-based-on-filter-criteria-in-postgres\"><span style=\"font-weight: 400\">precisam criar fun\u00e7\u00f5es<\/span><\/a><span style=\"font-weight: 400\"> apenas para executar algumas atualiza\u00e7\u00f5es b\u00e1sicas. Para mim, isso \u00e9 um sinal de que ainda precisamos de alguns aprimoramentos na linguagem de consulta.\u00a0<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">update `test` set address.zipcode = 94537, \r\n                  address.entrances = ARRAY_APPEND(address.entrances,  {\"name\": \"backyard\"}),\r\n                  permissions.roles = ARRAY_REMOVE(permissions.roles, \"ADMIN\") \r\n<\/pre>\n<p><span style=\"font-weight: 400\">Mesmo que n\u00e3o esteja familiarizado com o N1QL, voc\u00ea pode entender claramente o que est\u00e1 acontecendo na consulta acima, pois o N1QL tem <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/arrayfun.html\"><span style=\"font-weight: 400\">dezenas de fun\u00e7\u00f5es apenas para lidar com matrizes<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">SELECTs<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Como a sele\u00e7\u00e3o de dados \u00e9 um t\u00f3pico extenso, vamos dividi-lo em sess\u00f5es menores:<\/span><\/p>\n<h4><\/h4>\n<h4><span style=\"font-weight: 400\">Consulta de dados simples<\/span><\/h4>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">select address-&gt;'city' from users where address @&gt; '{\"zipcode\": \"94537\"}'\r\nselect * from users where address @&gt; '{\"entrances\":[{\"name\": \"backyard\"}]}'\r\n<\/pre>\n<p><span style=\"font-weight: 400\">O m\u00e1gico <\/span><strong>@&gt;<\/strong><span style=\"font-weight: 400\"> permite que voc\u00ea combine facilmente um par chave-valor ou um objeto dentro do seu JSON. De fato, ele facilita a correspond\u00eancia de coisas no JSON, embora haja algumas coisas que voc\u00ea deve ter em mente:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">\u00a0A operadora <\/span><b>@&gt; <\/b><span style=\"font-weight: 400\">suporta apenas compara\u00e7\u00f5es de igualdade<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Na segunda consulta, combinamos <\/span><b>quintal<\/b><span style=\"font-weight: 400\"> na matriz de entradas, mas a matriz real \u00e9, na verdade, a seguinte:<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">{\r\n...\r\n    \"entrances\": [\r\n        {\r\n            \"name\": \"main\"\r\n        },\r\n        {\r\n            \"name\": \"backyard\"\r\n        }\r\n    ],\r\n...\r\n}\r\n<\/pre>\n<p><span style=\"font-weight: 400\">Portanto, quando pesquisamos um atributo (CEP, neste primeiro caso), o <\/span><b>@&gt; <\/b><span style=\"font-weight: 400\">se comportou como <\/span><b>iguais<\/b><span style=\"font-weight: 400\">mas se usarmos o mesmo operador para pesquisar em uma matriz, ele se comportar\u00e1 como \"<\/span><b>cont\u00e9m<\/b><span style=\"font-weight: 400\">\".<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">Select address.city from `test` where\u00a0 address.zipcode = \u201894537\u2019;\r\nselect * from `test`\u00a0 where ANY entrance IN address.entrances SATISFIES entrance.name = \"main\" END;\r\nselect * from `test` as t where \"main\" within t; \/\/search for the occurence of \u201cmain\u201d inside the JSON<\/pre>\n<p><span style=\"font-weight: 400\">N\u00e3o h\u00e1 uma correla\u00e7\u00e3o direta entre o\u00a0 <\/span><b>@&gt;<\/b><span style=\"font-weight: 400\"> e uma palavra-chave no N1QL. Nas consultas acima, usamos estrat\u00e9gias diferentes para realizar as mesmas coisas. A sintaxe do Postgres \u00e9 mais curta para consultas muito simples, mas se voc\u00ea filtrar por dois ou tr\u00eas atributos, as consultas em N1QL ter\u00e3o aproximadamente o mesmo tamanho. Nesse caso, voc\u00ea tamb\u00e9m pode usar qualquer tipo de operador de compara\u00e7\u00e3o.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Um aspecto que considero positivo \u00e9 que as consultas que usam a sintaxe do SQL++ \"<\/span><b>se parecem mais com o SQL\"<\/b><span style=\"font-weight: 400\"> do que o SQL no pr\u00f3prio Postgres.\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Navegando pelos objetos<\/span><\/h3>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">select * from users where (address-&gt;&gt;'houseNumber')::int &gt; 5<\/pre>\n<p><span style=\"font-weight: 400\">O Postgres usa o <\/span><b>-&gt;&gt;<\/b><span style=\"font-weight: 400\"> para navegar pelas entidades e o operador <\/span><b>-&gt;<\/b><span style=\"font-weight: 400\"> para converter um atributo em texto. Mas se o atributo for um n\u00famero inteiro, ser\u00e1 necess\u00e1rio converter o id de volta para int.<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<pre class=\"lang:tsql decode:true\">Select * from `test` where address.houseNumber &gt; 5<\/pre>\n<p><span style=\"font-weight: 400\">No caso acima, voc\u00ea pode simplesmente navegar pelas entidades usando o \"<\/span><b>.<\/b><span style=\"font-weight: 400\">\" e o tipo adequado \u00e9 inferido automaticamente.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Tratamento de atributos ausentes\/existentes<\/span><\/h4>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<pre class=\"lang:pgsql decode:true\">select * from users where (preferences-&gt;'randomAttributeName\u2019') is\u00a0 null<\/pre>\n<p><span style=\"font-weight: 400\">O Postgres considera os valores ausentes como NULL, o que \u00e9 semanticamente errado:<\/span><\/p>\n<ul>\n<li><span style=\"font-weight: 400\">JSON com nulo \"<\/span><b>randomAttributeName''<\/b><span style=\"font-weight: 400\"> :<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">[\r\n    {\r\n        \"name\": \"lang\",\r\n        \"value\": \"en\",\r\n        \"timezone\": \"GMT+2\",\r\n        \"notification\": \"emailOnly\",\r\n       \u201crandomAttributeName\u2019': null\r\n    }\r\n]\r\n<\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li><span style=\"font-weight: 400\">JSON com \"<\/span><b>randomAttributeName''<\/b><span style=\"font-weight: 400\"> :<\/span><\/li>\n<\/ul>\n<pre class=\"lang:js decode:true\">[\r\n    {\r\n        \"name\": \"lang\",\r\n        \"value\": \"en\",\r\n        \"timezone\": \"GMT+2\",\r\n        \"notification\": \"emailOnly\"\r\n    }\r\n]\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Pode n\u00e3o ser muito importante para voc\u00ea neste momento, mas essa diferencia\u00e7\u00e3o ajuda a solucionar poss\u00edveis problemas no seu esquema ou quando voc\u00ea precisa atualizar as estruturas do pr\u00f3prio JSON.<\/span><\/p>\n<p><span style=\"font-weight: 400\">O<\/span><b> ?<\/b><span style=\"font-weight: 400\"> pode verificar se um atributo existe, mas s\u00f3 pode ser usado com chaves de n\u00edvel superior de acordo com o operador <\/span><a href=\"https:\/\/www.postgresql.org\/docs\/9.5\/functions-json.html\"><span style=\"font-weight: 400\">documentos<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">No N1QL, j\u00e1 existe uma sintaxe adequada para esse cen\u00e1rio:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select * from\u00a0 `test` where randomAttributeName is missing<\/pre>\n<p><span style=\"font-weight: 400\">Al\u00e9m disso, h\u00e1 tamb\u00e9m um a\u00e7\u00facar de sintaxe para verificar se o atributo existe (o mesmo que \"is not missing\"):<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select * from\u00a0 `test` where randomAttributeName exists<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">\u00cdndices\u00a0<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Os bancos de dados que permitem o armazenamento de dados como JSON geralmente n\u00e3o imp\u00f5em nenhum tipo de esquema, mas h\u00e1 um problema inerente quando voc\u00ea adiciona suporte flex\u00edvel a esquemas: Por padr\u00e3o, voc\u00ea n\u00e3o sabe antecipadamente quais documentos t\u00eam os atributos que voc\u00ea est\u00e1 consultando.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Esse problema pode ser resolvido rapidamente com a cria\u00e7\u00e3o de \u00edndices adequados, pois voc\u00ea pode reduzir significativamente o n\u00famero de documentos digitalizados e classific\u00e1-los de alguma forma para facilitar a localiza\u00e7\u00e3o do valor de destino. No entanto, como estamos lidando com JSON, os \u00edndices tamb\u00e9m precisam lidar com entidades e matrizes aninhadas, o que acrescenta um n\u00edvel extra significativo de complexidade.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Naturalmente, a cria\u00e7\u00e3o do \u00edndice correto para uma consulta tamb\u00e9m \u00e9 uma tarefa que exige alguma reflex\u00e3o. De fato, ~15% das perguntas nos f\u00f3runs do Couchbase s\u00e3o exatamente sobre isso. O Couchbase 6.5 vir\u00e1 at\u00e9 mesmo com um Indexer Recommender que sugerir\u00e1 um \u00edndice de acordo com uma determinada consulta:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7356\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p5-1024x559.png\" alt=\"\" width=\"900\" height=\"491\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-1024x559.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-300x164.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-768x419.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5-20x11.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p5.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<h4><span style=\"font-weight: 400\">Postgres:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Os \u00edndices para dados JSONB s\u00e3o um dos mais novos recursos do Postgres, e os desenvolvedores est\u00e3o realmente empolgados com isso, pois o desempenho das consultas aumentar\u00e1 significativamente em compara\u00e7\u00e3o com as vers\u00f5es anteriores.  De acordo com a documenta\u00e7\u00e3o principal, o Postgres oferece suporte a dois tipos de \u00edndices: o padr\u00e3o e o <\/span><b>jsonb_path_ops<\/b><span style=\"font-weight: 400\">:<\/span><\/p>\n<p><b>Padr\u00e3o<\/b><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE INDEX idxusersall ON users USING GIN (address);<\/pre>\n<p><span style=\"font-weight: 400\">Esse \u00edndice permite que voc\u00ea use consultas com os operadores de n\u00edvel superior key-exists ?, ?&amp; e ?| e o operador path\/value-exists @&gt; . <\/span><span style=\"font-weight: 400\">Al\u00e9m disso, voc\u00ea tamb\u00e9m pode indexar um campo espec\u00edfico:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX idxusers ON users USING GIN ((address -&gt; 'entrances'));<\/pre>\n<p><span style=\"font-weight: 400\">Para o GIN Index, voc\u00ea s\u00f3 pode especificar um \u00fanico campo.<\/span><\/p>\n<p><b>jsonb_path_ops<\/b><\/p>\n<pre class=\"lang:pgsql decode:true\">CREATE INDEX idxginp ON api USING GIN (jdoc jsonb_path_ops);<\/pre>\n<p><span style=\"font-weight: 400\">A classe do operador GIN n\u00e3o padr\u00e3o jsonb_path_ops suporta a indexa\u00e7\u00e3o somente do operador @&gt;. Normalmente, isso resultar\u00e1 em um \u00edndice menor e mais r\u00e1pido. Voc\u00ea pode <\/span><a href=\"https:\/\/www.postgresql.org\/docs\/current\/datatype-json.html#JSON-INDEXING\"><span style=\"font-weight: 400\">Leia mais sobre isso aqui<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<h4><strong>Atualiza\u00e7\u00e3o do artigo:\u00a0<\/strong><\/h4>\n<p>Mark (que comentou aqui neste artigo) e @postgresmen no Twitter destacaram que voc\u00ea pode criar \u00edndices com v\u00e1rios campos usando BTrees ou GIST:<\/p>\n<pre class=\"lang:pgsql decode:true\">\/\/ for a JSONB collumn called \"data\" with the following content:\r\n\/\/ {\"a\": %s, \"b\":2, \"c\":1, \"d\":3}\r\ncreate index t1_l2 on users using btree((address-&gt;&gt;'a'), (address-&gt;&gt;'b'), (address-&gt;&gt;'c'));<\/pre>\n<p>Em seguida, voc\u00ea pode usar o \u00edndice acima com a seguinte consulta:<\/p>\n<pre class=\"lang:pgsql decode:true\">select from t1 where address-&gt;&gt;'a' = 1::text<\/pre>\n<p>Voc\u00ea tamb\u00e9m pode usar \u00edndices parciais com a sintaxe acima:<\/p>\n<pre class=\"lang:pgsql decode:true\">create index t1_l3 on users using btree((address-&gt;&gt;'a'), (address-&gt;&gt;'b'), (address-&gt;&gt;'c')) \r\nwhere address-&gt;'state' = '\"CA\"';<\/pre>\n<p><span style=\"font-weight: 400\">O <\/span><a href=\"https:\/\/www.postgresql.org\/files\/documentation\/pdf\/11\/postgresql-11-US.pdf\"><span style=\"font-weight: 400\">A documenta\u00e7\u00e3o oficial tem apenas 2 p\u00e1ginas sobre como indexar campos JSONB,<\/span><\/a><span style=\"font-weight: 400\"> s\u00f3 depois que Mark\/@postgresmen me informou, pude descobrir como criar determinados tipos de \u00edndices. Indexa\u00e7\u00e3o JSONB <\/span><span style=\"font-weight: 400\">deve receber <a href=\"https:\/\/www.youtube.com\/watch?v=VyjrEhr6RsU\">atualiza\u00e7\u00f5es interessantes nas pr\u00f3ximas vers\u00f5es do Postgres<\/a>.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h4><span style=\"font-weight: 400\">Couchbase:<\/span><\/h4>\n<p><span style=\"font-weight: 400\">Os \u00edndices s\u00e3o, na verdade, o n\u00facleo do Couchbase. Atualmente, oferecemos suporte a 7 tipos diferentes:<\/span><\/p>\n<ul>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/createprimaryindex.html\"><b>Prim\u00e1rio<\/b><\/a><b> &#8211;<\/b><span style=\"font-weight: 400\"> Indexa todo o compartimento na chave do documento<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/learn\/services-and-indexes\/indexes\/global-secondary-indexes.html\"><b>Secund\u00e1rio<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">Indexa um escalar, objeto ou matriz usando um valor-chave<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/covering-indexes.html\"><b>Composto\/Coberto<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">V\u00e1rios campos armazenados em um \u00edndice<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#functional-index\"><b>Funcional<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">\u00cdndice secund\u00e1rio que permite express\u00f5es funcionais em vez de um simples valor-chave<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#array-index\"><b>Matriz<\/b><\/a><b> &#8211; <\/b><span style=\"font-weight: 400\">Um \u00edndice de elementos de matriz que varia de valores escalares simples a matrizes complexas ou objetos JSON aninhados mais profundamente na matriz.<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/adaptive-indexing.html\"><b>Adaptativo<\/b><\/a><b> &#8211;<\/b><span style=\"font-weight: 400\"> \u00cdndice de matriz secund\u00e1ria para todos ou alguns campos de um documento sem a necessidade de defini-los antecipadamente.<\/span><\/li>\n<li><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/services-and-indexes\/indexes\/indexing-and-query-perf.html#partial-index\"><b>\u00cdndice parcial -<\/b><\/a> <span style=\"font-weight: 400\">Permite que voc\u00ea indexe apenas um subconjunto de seus dados<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Como voc\u00ea pode ver, os \u00edndices s\u00e3o algo bastante maduro no Couchbase e muito mais flex\u00edveis do que os suportados pelo Postgres JSONB. N\u00e3o vou me aprofundar no assunto, pois este artigo j\u00e1 est\u00e1 bem longo. Gostaria apenas de destacar duas coisas que, pessoalmente, acho muito legais: \u00cdndices parciais cobertos e Aggregate Pushdowns<\/span><\/p>\n<p>&nbsp;<\/p>\n<h5><b>\u00cdndices parciais cobertos\u00a0<\/b><\/h5>\n<p><span style=\"font-weight: 400\">Com uma combina\u00e7\u00e3o de Covered e Partial, voc\u00ea pode criar \u00edndices apenas para o subconjunto de dados que lhe interessa.\u00a0<\/span><\/p>\n<p><b>EX:<\/b><span style=\"font-weight: 400\"> Digamos que voc\u00ea tenha um jogo on-line e precise mostrar uma tabela de classifica\u00e7\u00e3o por pa\u00eds, al\u00e9m de ignorar usu\u00e1rios inativos ou com menos de 10 pontos. O desempenho de sua tabela de classifica\u00e7\u00e3o \u00e9 bom para todos os pa\u00edses, exceto para a China, que tem 10 vezes mais jogadores. Nesse caso, voc\u00ea poderia criar um \u00edndice espec\u00edfico para melhorar a velocidade de sua consulta:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX `china_leader_board` ON\r\n`user_profiles`(\r\n   username,\r\n   points DESC)\r\nWHERE active = true\r\n   and countryCode = \"CN\" and points &gt; 10<\/pre>\n<p><span style=\"font-weight: 400\">Observe que j\u00e1 estamos mantendo os pontos ordenados, portanto, uma consulta como a seguinte deve ser extremamente r\u00e1pida:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">Select username, points from user_profiles where active = true\u00a0\u00a0\u00a0and countryCode = \"CN\" order by points DESC limit 20<\/pre>\n<p>&nbsp;<\/p>\n<h5><b>Flex\u00f5es agregadas<\/b><\/h5>\n<p><span style=\"font-weight: 400\">A agrega\u00e7\u00e3o \u00e9 sempre uma tarefa dif\u00edcil para armazenamentos sem colunas. No Couchbase, permitimos que voc\u00ea crie \u00edndices para tornar a agrega\u00e7\u00e3o mais r\u00e1pida. Vejamos o exemplo a seguir:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">SELECT country, state, city, COUNT(1) AS total\r\nFROM `travel-sample`\r\nWHERE type = 'hotel' and country is not null\r\nGROUP BY country, state, city\r\nORDER BY COUNT(1) DESC;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Essa consulta levou cerca de 90 ms para ser executada. Aqui est\u00e1 o plano de consulta:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7357\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p6-1024x159.png\" alt=\"\" width=\"900\" height=\"140\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-1024x159.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-300x47.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-768x119.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6-20x3.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p6.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">Agora, vamos criar o seguinte \u00edndice:<\/span><\/p>\n<pre class=\"lang:tsql decode:true\">CREATE INDEX ix_hotelregions ON `travel-sample` (country, state, city) WHERE type='hotel';<\/pre>\n<p><span style=\"font-weight: 400\">Se executarmos a mesma consulta novamente, ela dever\u00e1 ser executada em aproximadamente 7 ms. Observe que no novo plano de consulta n\u00e3o h\u00e1 nenhuma etapa de \"grupo\":<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-7358\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/p7-1024x152.png\" alt=\"\" width=\"900\" height=\"134\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-1024x152.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-300x45.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-768x114.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7-20x3.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/p7.png 1300w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Voc\u00ea pode<\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/groupby-aggregate-performance.html\"><span style=\"font-weight: 400\"> Leia mais sobre os \u00edndices do Couchbase aqui\u00a0<\/span><\/a><\/p>\n<p><b>Observa\u00e7\u00e3o<\/b><span style=\"font-weight: 400\">: travel-sample \u00e9 um dos bancos de dados de demonstra\u00e7\u00e3o que voc\u00ea pode carregar ao instalar o Couchbase<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><b>Desempenho<\/b><\/h2>\n<p><span style=\"font-weight: 400\">Embora ambos os bancos de dados sejam considerados CP (Consistent\/Partition Tolerant), o Postgres \u00e9 um RDBMS mestre\/escravo tradicional, enquanto o Couchbase \u00e9 otimizado para leituras\/escritas r\u00e1pidas em escala e suporte adicional para <\/span><a href=\"https:\/\/jepsen.io\/consistency\/models\/monotonic-atomic-view\"><span style=\"font-weight: 400\">Vis\u00f5es at\u00f4micas monot\u00f4nicas<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">Infelizmente, h\u00e1 apenas alguns benchmarks de JSONB publicados on-line e, nos mais recentes, o Postgres foi<\/span><a href=\"https:\/\/www.youtube.com\/watch?v=4c-Q_rEZ9K8&amp;feature=youtu.be\"><span style=\"font-weight: 400\"> relatado como sendo mais r\u00e1pido que o Mongo em uma inst\u00e2ncia de n\u00f3 \u00fanico<\/span><\/a><span style=\"font-weight: 400\"> (<\/span><a href=\"https:\/\/www.postgresql.eu\/events\/fosdem2018\/sessions\/session\/1691\/slides\/63\/High-Performance%20JSON_%20PostgreSQL%20Vs.%20MongoDB.pdf\"><span style=\"font-weight: 400\">aqui tamb\u00e9m<\/span><\/a><span style=\"font-weight: 400\">). Os resultados s\u00e3o impressionantes, mas vale a pena destacar que a maioria dessas compara\u00e7\u00f5es foi feita com apenas um ou dois n\u00f3s, o que \u00e9 um cen\u00e1rio que favorece o RDBMS em geral.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">N\u00e3o quero enfatizar a arquitetura do Couchbase aqui, mas como um banco de dados que prioriza a mem\u00f3ria, seu aplicativo recebe a confirma\u00e7\u00e3o de uma grava\u00e7\u00e3o bem-sucedida assim que o banco de dados recebe a solicita\u00e7\u00e3o e, em seguida, seu documento \u00e9 replicado de forma ass\u00edncrona e gravado no disco (sim, voc\u00ea tamb\u00e9m pode alterar quando deseja receber a confirma\u00e7\u00e3o).\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Se acrescentarmos a isso o fato de que o Couchbase tem uma arquitetura sem mestre (seu aplicativo envia as grava\u00e7\u00f5es\/leituras diretamente para o servidor certo), um suporte de indexa\u00e7\u00e3o muito melhor e a alta escalabilidade (h\u00e1 clientes executando clusters de CB \u00fanico em produ\u00e7\u00e3o com mais de 100 n\u00f3s), fica claro para mim qual deles ter\u00e1 melhor desempenho em escala, a quest\u00e3o \u00e9 apenas \"quanto\".<\/span><\/p>\n<p><span style=\"font-weight: 400\">Ainda n\u00e3o h\u00e1 um benchmark entre Postgres e Couchbase. Se voc\u00ea quiser ver um, envie um tweet para <\/span><a href=\"https:\/\/twitter.com\/deniswsrosa\"><span style=\"font-weight: 400\">@deniswsrosa<\/span><\/a><span style=\"font-weight: 400\">. Enquanto isso, voc\u00ea pode comparar indiretamente o desempenho de ambos usando o seguinte <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/pt\/benchmarks\/\"><span style=\"font-weight: 400\">Refer\u00eancia em Couchbase\/Mongo\/Cassandra<\/span><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Conclus\u00e3o<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Estou realmente empolgado com o aumento do suporte a JSON no Postgres, pois isso certamente far\u00e1 com que os desenvolvedores se familiarizem mais com os benef\u00edcios do armazenamento de dados como JSON e, consequentemente, tornar\u00e1 os bancos de dados de documentos tamb\u00e9m mais populares.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Muitas ferramentas e estruturas no mercado j\u00e1 oferecem suporte a dados JSON e, \u00e0 medida que a ado\u00e7\u00e3o do Postgres JSONB aumenta, ele deve se tornar um recurso padr\u00e3o, o que \u00e9 novamente uma coisa boa para todos os usu\u00e1rios. <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/resources\/why-nosql\/\">Banco de dados NoSQL<\/a>.<\/span><\/p>\n<p><span style=\"font-weight: 400\">No entanto, h\u00e1 algumas coisas que devem ser levadas em conta antes de entrar no JSONB do Postgres:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><b>Linguagem de consulta complexa: <\/b><span style=\"font-weight: 400\">A linguagem de consulta atual para JSONB n\u00e3o \u00e9 intuitiva; mesmo depois de ler os documentos, ainda \u00e9 um pouco complexo entender o que est\u00e1 acontecendo na consulta. O PG 12 pode resolver alguns desses problemas com o <\/span><b>Linguagem de caminho JSON<\/b><span style=\"font-weight: 400\">mas ainda parecer\u00e1 uma mistura de alguma outra linguagem com SQL. Eu preferiria ver o Postgres adicionando suporte ao SQL++.<\/span><\/li>\n<li style=\"font-weight: 400\"><b>Linguagem de consulta limitada:<\/b><span style=\"font-weight: 400\"> Al\u00e9m de ser complexa, a linguagem de consulta ainda n\u00e3o est\u00e1 pronta. Faltam fun\u00e7\u00f5es para manipular os dados JSON; por exemplo, voc\u00ea precisa usar algumas solu\u00e7\u00f5es alternativas apenas para fazer algumas manipula\u00e7\u00f5es b\u00e1sicas de matriz. Se voc\u00ea tiver um JSON muito din\u00e2mico e precisar consult\u00e1-lo de v\u00e1rias maneiras, as coisas podem se tornar realmente desafiadoras. <\/span>Parece que o foco principal at\u00e9 agora foi construir a ponte entre o JSON e os dados relacionais.<\/li>\n<li style=\"font-weight: 400\"><b>Indexa\u00e7\u00e3o:<\/b><span style=\"font-weight: 400\"> Com o novo tipo de \u00edndice, as consultas ser\u00e3o executadas muito mais rapidamente do que antes. Al\u00e9m disso, voc\u00ea pode usar o BTree e o Gist para cobrir casos n\u00e3o compat\u00edveis com o GIN.<\/span><\/li>\n<li><b>Documenta\u00e7\u00e3o superficial: <span style=\"font-weight: 400\">H\u00e1 apenas cerca de 6 p\u00e1ginas de documenta\u00e7\u00e3o falando sobre JSONB. A maioria das coisas que aprendi ao escrever este artigo foi baseada em tentativa e erro, perguntas do StackOverflow, publica\u00e7\u00f5es em blogs e apresenta\u00e7\u00f5es no YouTube.\u00a0<\/span><\/b><\/li>\n<li style=\"font-weight: 400\"><b>Ferramentas<\/b><span style=\"font-weight: 400\">: N\u00e3o mencionei isso durante o artigo, mas como se trata de um recurso bastante novo, \u00e9 natural que algumas estruturas\/SDKs ainda n\u00e3o tenham adicionado suporte total a ele. Vamos pegar o SpringData como exemplo, existem alguns <\/span><a href=\"https:\/\/stackoverflow.com\/questions\/51276703\/how-to-store-postgresql-jsonb-using-springboot-jpa\"><span style=\"font-weight: 400\">esfor\u00e7os comunit\u00e1rios<\/span><\/a><span style=\"font-weight: 400\"> mas n\u00e3o \u00e9 uma experi\u00eancia totalmente tranquila. Voc\u00ea pode esperar alguns contratempos ao longo do caminho.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Alguns dos problemas acima s\u00e3o conhecidos, e algumas palestras\/artigos com links neste artigo at\u00e9 os mencionam. Os mais cr\u00edticos j\u00e1 est\u00e3o no roadmap para as pr\u00f3ximas vers\u00f5es do Postgres.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Ao contr\u00e1rio da maioria das apresenta\u00e7\u00f5es populares a que assisti, n\u00e3o acho que ele ainda seja adequado para modelos muito din\u00e2micos, principalmente porque a consulta e a manipula\u00e7\u00e3o de dados n\u00e3o s\u00e3o t\u00e3o f\u00e1ceis quanto poderiam ser.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Onde o Postgres JSONB \u00e9 uma boa op\u00e7\u00e3o?<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Embora eu tenha apontado alguns problemas do meu ponto de vista, acho que esse \u00e9 um recurso valioso e voc\u00ea deve definitivamente considerar us\u00e1-lo. Aqui est\u00e3o alguns cen\u00e1rios em que acho que ele se encaixa bem:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">CQRS\/<a href=\"https:\/\/www.couchbase.com\/blog\/pt\/event-sourcing-event-logging-an-essential-microservice-pattern\/\">Sourcing de eventos<\/a> sistemas que precisam ser altamente transacionais<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Metadados<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Evitar uni\u00f5es desnecess\u00e1rias, armazenando algumas entidades relacionadas como JSONBs<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Sempre que voc\u00ea precisar armazenar cadeias de caracteres codificadas em JSON, mas n\u00e3o precisar manipular ou consultar os dados com muita frequ\u00eancia.<\/span><\/li>\n<\/ul>\n<p>Nos casos acima, o Postgres deve funcionar bem, mesmo em grandes implementa\u00e7\u00f5es. Os \u00edndices podem ficar um pouco grandes com o GIN, mas ainda s\u00e3o gerenci\u00e1veis.<\/p>\n<p>&nbsp;<\/p>\n<h3><span style=\"font-weight: 400\">Onde o Couchbase \u00e9 uma boa op\u00e7\u00e3o?<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Tenho trabalhado com sucesso com bancos de dados de documentos h\u00e1 mais de quatro anos e, a essa altura, posso ser um pouco tendencioso, mas acho que os cen\u00e1rios em que ele pode ser usado como substituto de um RDBMS s\u00e3o muito maiores do que voc\u00ea imagina. Alguns dos casos de uso mais famosos s\u00e3o:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Armazenamento de perfis de usu\u00e1rios;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Cat\u00e1logos de produtos\/Carrinhos de compras;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Hist\u00f3rico m\u00e9dico (para o HealthCare);<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Contratos, ap\u00f3lices de seguro;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">M\u00eddia social;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Jogos;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Armazenamento em cache;<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">&#8230;<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">De fato, a maioria dos sistemas que n\u00e3o requerem <\/span><a href=\"https:\/\/jepsen.io\/consistency\/models\/serializable\"><span style=\"font-weight: 400\">transa\u00e7\u00f5es fortemente serializ\u00e1veis<\/span><\/a><span style=\"font-weight: 400\"> entre v\u00e1rios documentos deve ser uma boa op\u00e7\u00e3o, o que n\u00e3o significa que as transa\u00e7\u00f5es n\u00e3o sejam suportadas, \u00e9 apenas uma vers\u00e3o mais relaxada que n\u00e3o comprometer\u00e1 a escalabilidade do banco de dados, especialmente com o Couchbase 6.5!<\/span><\/p>\n<p><span style=\"font-weight: 400\">O Couchbase CE e EE realmente brilham quando voc\u00ea precisa de desempenho em escala. Voc\u00ea pode criar facilmente clusters com 3, 5, 10, 50, 100 n\u00f3s e ainda assim manter um bom desempenho e uma consist\u00eancia forte, e \u00e9 por isso que ele \u00e9 atualmente uma das principais op\u00e7\u00f5es para aplicativos de miss\u00e3o cr\u00edtica. Se voc\u00ea tiver tempo, confira alguns dos <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/pt\/customers\/\"><span style=\"font-weight: 400\">casos de uso p\u00fablico<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Todos esses casos de uso cr\u00edticos ao longo dos anos tornaram o N1QL e a indexa\u00e7\u00e3o muito s\u00f3lidos, r\u00e1pidos e flex\u00edveis. \u00c9 por isso que considero uma compara\u00e7\u00e3o injusta, dado o estado atual do Postgres JSONB, embora seja v\u00e1lida para mostrar aos desenvolvedores as lacunas entre uma implementa\u00e7\u00e3o inicial e o melhor suporte a JSON at\u00e9 o momento.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Se voc\u00ea tiver alguma d\u00favida, coment\u00e1rio ou discordar completamente de mim, sinta-se \u00e0 vontade para me enviar um tweet para <a href=\"https:\/\/twitter.com\/deniswsrosa\">@deniswsrosa<\/a><\/span><\/p>","protected":false},"excerpt":{"rendered":"<p>The reality is that databases are converging, and in the last few years, it is becoming even more difficult to point what are the best scenarios for each datastore without a deep understanding of how things work under the hood.\u00a0 [&hellip;]<\/p>","protected":false},"author":8754,"featured_media":10650,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1812],"tags":[],"ppma_author":[9059],"class_list":["post-7351","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-n1ql-query"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Comparing Postgres JSONB With NoSQL Databases | Learn More<\/title>\n<meta name=\"description\" content=\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/postgres-jsonb-and-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Comparing Postgres JSONB With NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/postgres-jsonb-and-nosql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-08-06T13:57:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-26T19:09:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/Couchbase-postgres_RESIZED.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2200\" \/>\n\t<meta property=\"og:image:height\" content=\"635\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Denis Rosa, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@deniswsrosa\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Denis Rosa, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"},\"author\":{\"name\":\"Denis Rosa, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257\"},\"headline\":\"Comparing Postgres JSONB With NoSQL\",\"datePublished\":\"2019-08-06T13:57:07+00:00\",\"dateModified\":\"2023-07-26T19:09:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"},\"wordCount\":3371,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"articleSection\":[\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\",\"name\":\"Comparing Postgres JSONB With NoSQL Databases | Learn More\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"datePublished\":\"2019-08-06T13:57:07+00:00\",\"dateModified\":\"2023-07-26T19:09:43+00:00\",\"description\":\"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png\",\"width\":2200,\"height\":635,\"caption\":\"Learn how to compare Postgres JSONB with a NoSQL database.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Comparing Postgres JSONB With NoSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257\",\"name\":\"Denis Rosa, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/be0716f6199cfb09417c92cf7a8fa8d6\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g\",\"caption\":\"Denis Rosa, Developer Advocate, Couchbase\"},\"description\":\"Denis Rosa is a Developer Advocate for Couchbase and lives in Munich - Germany. He has a solid experience as a software engineer and speaks fluently Java, Python, Scala and Javascript. Denis likes to write about search, Big Data, AI, Microservices and everything else that would help developers to make a beautiful, faster, stable and scalable app.\",\"sameAs\":[\"https:\/\/x.com\/deniswsrosa\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/denis-rosa\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Comparing Postgres JSONB With NoSQL Databases | Learn More","description":"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/postgres-jsonb-and-nosql\/","og_locale":"pt_BR","og_type":"article","og_title":"Comparing Postgres JSONB With NoSQL","og_description":"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/postgres-jsonb-and-nosql\/","og_site_name":"The Couchbase Blog","article_published_time":"2019-08-06T13:57:07+00:00","article_modified_time":"2023-07-26T19:09:43+00:00","og_image":[{"width":2200,"height":635,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2019\/08\/Couchbase-postgres_RESIZED.png","type":"image\/png"}],"author":"Denis Rosa, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@deniswsrosa","twitter_misc":{"Written by":"Denis Rosa, Developer Advocate, Couchbase","Est. reading time":"16 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"},"author":{"name":"Denis Rosa, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257"},"headline":"Comparing Postgres JSONB With NoSQL","datePublished":"2019-08-06T13:57:07+00:00","dateModified":"2023-07-26T19:09:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"},"wordCount":3371,"commentCount":5,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","articleSection":["SQL++ \/ N1QL Query"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/","name":"Comparing Postgres JSONB With NoSQL Databases | Learn More","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","datePublished":"2019-08-06T13:57:07+00:00","dateModified":"2023-07-26T19:09:43+00:00","description":"Learn the different use cases for when to use Postgres 11 with JSONB and when to use a NoSQL database such as Couchbase. Start learning with Couchbase today.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2019\/08\/Couchbase-postgres_RESIZED.png","width":2200,"height":635,"caption":"Learn how to compare Postgres JSONB with a NoSQL database."},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/postgres-jsonb-and-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Comparing Postgres JSONB With NoSQL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/fe3c5273e805e72a5294611a48f62257","name":"Denis Rosa, defensor dos desenvolvedores, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/be0716f6199cfb09417c92cf7a8fa8d6","url":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","caption":"Denis Rosa, Developer Advocate, Couchbase"},"description":"Denis Rosa \u00e9 um Developer Advocate do Couchbase e mora em Munique, na Alemanha. Ele tem uma s\u00f3lida experi\u00eancia como engenheiro de software e fala fluentemente Java, Python, Scala e Javascript. Denis gosta de escrever sobre pesquisa, Big Data, IA, microsservi\u00e7os e tudo o mais que possa ajudar os desenvolvedores a criar um aplicativo bonito, mais r\u00e1pido, est\u00e1vel e escal\u00e1vel.","sameAs":["https:\/\/x.com\/deniswsrosa"],"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/denis-rosa\/"}]}},"authors":[{"term_id":9059,"user_id":8754,"is_guest":0,"slug":"denis-rosa","display_name":"Denis Rosa, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/f8d1f5c13115122cab89d0f229b904480bfe20d3dfbb093fe9734cda5235d419?s=96&d=mm&r=g","first_name":"Denis","last_name":"Rosa, Developer Advocate, Couchbase","user_url":"","author_category":"","description":"Denis Rosa \u00e9 um Developer Advocate do Couchbase e mora em Munique, na Alemanha. Ele tem uma s\u00f3lida experi\u00eancia como engenheiro de software e fala fluentemente Java, Python, Scala e Javascript. Denis gosta de escrever sobre pesquisa, Big Data, IA, microsservi\u00e7os e tudo o mais que possa ajudar os desenvolvedores a criar um aplicativo bonito, mais r\u00e1pido, est\u00e1vel e escal\u00e1vel."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/7351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/8754"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=7351"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/7351\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/10650"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=7351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=7351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=7351"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=7351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}