PostgreSQL is an open-source DBMS that is comprised of both object and relational models. It has different data types to store and process the data. More information on data types can be found here.
JSON is a human-readable format for storing data. Please note that PostgreSQL has two data types for JSON. Let’s discuss it further below.
json
and jsonb
The commonality between json
and jsonb
is that we can store the same data type in both. Handling nested objects in json
and jsonb
is easier than denormalizing the data into columns or multiple tables.
Let’s discuss the differences between these below:
Data storage: json
stores data in the same format we’ve used, like ASCII/UTF-8. It also undergoes parsing. On the other hand, jsonb
stores the data in the binary format, and no reparsing is required when using this data type.
Query performance: json
doesn’t support indexing directly, and it takes much time when data processing is required. On the other hand, jsonb
is faster than json
whenever data processing is required.
Duplicate keys: Ordering of the keys and whitespaces are preserved in json
. However, jsonb
removes the whitespaces from the input data. It also orders the data and store’s the last value in the key in case of duplicates.
Let’s summarize the details in the table below:
JSON | JSONB | |
Storage | Preserves the format | Changes it to binary format |
Parsing time | Less | More |
Reparsing required | No | Yes |
Indexing | Doesn't support directly | Supported |
Data processing | Slow | Fast |
Whitespaces | Preserves whitespaces | Removes whitespaces |
Ordering of keys | Preserved | Ordered by keys |
Duplicates | Preserved | Not allowed (Last assigned value will be stored in the key) |
Let’s create a table, Animals
, with columns animal_id
, specifications
, and specifications_b
. The column animal_id
stores the ID of each entry. The column specifications
stores the data using the json
data type. The column specifications_b
stores the data using the jsonb
data type. Then, insert a few records into it.
CREATE TABLE Animals (animal_id SERIAL PRIMARY KEY,specifications JSON,specifications_b JSONB);INSERT INTO Animals (specifications, specifications_b)VALUES('{"name": "Hope", "species": "chicken", "sound": "cluck", "traits": {"claws": "true", "fin": "false", "feathers": "true"}}' :: json, '{"name": "Hope", "species": "chicken", "sound": "cluck", "traits": {"claws": "true", "fur": "false", "feathers": "true"}}' :: jsonb),('{"name": "Daisy", "species": "fish", "sound": "N/A", "traits": {"claws": "false", "fin": "true", "feathers": "false"}}' :: json, '{"name": "Daisy", "species": "Fish", "sound": "N/A", "traits": {"claws": "false", "fin": "true", "feathers": "false"}}' :: jsonb),('{"name": "Max", "species": "duck", "sound": "quack", "traits": {"claws": "true", "fin": "false", "feathers": "true"}}' :: json, '{"name": "Max", "species": "duck", "sound": "quack", "traits": {"claws": "true", "fin": "false", "feathers": "true"}}' :: jsonb),('{"name": "Bella", "species": "cat", "sound": "meow", "traits": {"claws": "true", "fin": "false", "feathers": "false"}}' :: json, '{"name": "Bella", "species": "cat", "sound": "meow", "traits": {"claws": "true", "fin": "false", "feathers": "false"}}' :: jsonb),('{"name": "Rocky", "species": "lion", "sound": "roar", "traits": {"claws": "true", "fin": "false", "feathers": "false"}}' :: json, '{"name": "Rocky", "species": "lion", "sound": "roar", "traits": {"claws": "true", "fin": "false", "feathers": "false"}}' :: jsonb);
We have inserted the data in the Animals
table. Please note that ->
and -->
are native operators in PostgreSQL. The former is used to return a JSON object, and the latter is used to get the output as text. We can use these operators with json
and jsonb
.
Let’s write a few queries to retrieve the information from the data. First, retrieve the data from the specifications
column, which is of json
data type, using the following query:
SELECT specificationsFROM Animals;
Let’s do the same for the specifications_b
column, which is of jsonb
data type, using the following query:
SELECT specifications_bFROM Animals;
Then, we will retrieve the data where the sound of the animal is roar
in the specifications_b
column. Have a look at the query below:
SELECT specifications_bFROM AnimalsWHERE specifications_b -> 'sound' ? 'roar';
Let’s say we want to know the species of the animal where the sound of the animal is roar
in the specifications
column. Look at the query below:
SELECT specifications ->> 'species' AS speciesFROM AnimalsWHERE specifications ->> 'sound' = 'roar';
Let’s do the same with the data in the specifications_b
column. Look at the query below:
SELECT specifications_b ->> 'species' AS speciesFROM AnimalsWHERE specifications_b ->> 'sound' = 'roar';
Next, find the animal without claws in the specifications_b
column. In this way, we will access the nested data. Look at the query below:
SELECT animal_id, specifications_bFROM AnimalsWHERE specifications_b -> 'traits' ->> 'claws' = 'false';
Please note that there is no difference between the output of both data types. Let’s explore the additional capabilities of jsonb
in PostgreSQL. The jsonb
data type supports indexing, enabling faster and more efficient queries. We’ll create a GIN index in the following query.
-- Create an index on a JSONB columnCREATE INDEX idx_specsON AnimalsUSING GIN (specifications_b);-- Query using the indexSELECT specifications_bFROM AnimalsWHERE specifications_b ->> 'species' = 'cat';
JSON is a text-based format suitable for storing and exchanging data, while JSONB is a binary storage format optimized for efficient querying, indexing, and storage space. The choice between JSON and JSONB depends on query performance, storage efficiency, and the need for dynamic querying or frequent data modifications.
Free Resources