In PostgreSQL ( as well as in other rdbms ) you can define columns as arrays. What I wondered is: What is more efficient when it comes to space: Creating several columns or just creating once column as array? The result, at least for me, is rather surprising.

Read More

First, let’s create a table with columns of type int:

postgres=# create table single_values ( a int, b int, c int, d int, e int, f int, g int, h int, i int, j int );
CREATE TABLE
postgres=# \d single_values
 Table "public.single_values"
 Column |  Type   | Modifiers 
--------+---------+-----------
 a      | integer | 
 b      | integer | 
 c      | integer | 
 d      | integer | 
 e      | integer | 
 f      | integer | 
 g      | integer | 
 h      | integer | 
 i      | integer | 
 j      | integer | 

Next create a table with just one column of type array[int]:

postgres=# create table arr_values ( a int[] );
CREATE TABLE

Ready for populating the first table;

truncate table single_values;
\timing on
Timing is on.
DO $$DECLARE
  ln int := 1000;
BEGIN
  for i in 0..1e6 loop
    insert into single_values (a,b,c,d,e,f,g,h,i,j)
           values (ln,ln,ln,ln,ln,ln,ln,ln,ln,ln);
  end loop;
END$$;
DO
Time: 4225.313 ms
postgres=# 

And the table with the array column:

truncate table arr_values;
 \timing on
 Timing is on.
 DO $$DECLARE
 larr int[] := '{1000,1000,1000,1000,1000,1000,1000,1000,1000,1000}';
 BEGIN
 for i in 0..1e6 loop
 insert into arr_values (a)
 values (larr);
 end loop;
 END$$;
postgres=# \i populate_arr_values.sql
 TRUNCATE TABLE
 DO
 Time: 4033.523 ms
 postgres=#

Now, what about the size?

postgres=# select pg_size_pretty(pg_relation_size('single_values'));
 pg_size_pretty 
----------------
 65 MB
(1 row)

Time: 0.227 ms
postgres=# select pg_size_pretty(pg_relation_size('arr_values'));
 pg_size_pretty 
----------------
 89 MB
(1 row)

Time: 0.737 ms

I did expect the table with the array to be smaller but it is the other way around. The table with the 10 columns is smaller. In the next post I’ll do the same for oracle.