Бенчмарк: bigint vs int на PostgreSQL


Я хочу повысить производительность своей базы данных. В проекте все таблицы перешли от int к bigint, что я считаю плохим выбором не только в отношении хранения, поскольку int требует 4 bytes, а bigint требует 8 bytes; но и в отношении производительности. Поэтому я создал небольшую таблицу с10 миллионами записей, со скриптом в Python:

import uuid

rows=10000000

output='insert_description_bigint.sql'
f = open(output, 'w')

set_schema="SET search_path = norma;n"
f.write(set_schema)

for i in range(1,rows):
    random_string=uuid.uuid4()
    query="insert into description_bigint (description_id, description) values (%d, '%s'); n"
    f.write(query % (i,random_string))

И вот как я создал свои two таблицы:

-- BIGINT

DROP TABLE IF EXISTS description_bigint;

CREATE TABLE description_bigint
(
  description_id BIGINT PRIMARY KEY NOT NULL,
  description VARCHAR(200),
  constraint description_id_positive CHECK (description_id >= 0)
);

select count(1) from description_bigint;
select * from description_bigint;
select * from description_bigint where description_id = 9999999;

-- INT

DROP TABLE IF EXISTS description_int;

CREATE TABLE description_int
(
  description_id INT PRIMARY KEY NOT NULL,
  description VARCHAR(200),
  constraint description_id_positive CHECK (description_id >= 0)
);

После вставки всех этих данных я делаю запрос для обеих таблиц, чтобы измерить разница между ними. И к моему удивлению, они оба имеют одинаковое представление:

select * from description_bigint; -- 11m55s
select * from description_int; -- 11m55s

Я делаю что-то не так с моим эталоном ? Разве int не должно быть быстрее, чем bigint ? Особенно, когда primary key по определению является index, что означает, что создание индекса для bigint будет медленнее, чем создание индекса для int, с тем же количеством данных, верно ?

Я знаю, что это не просто мелочь, которая окажет огромное влияние на мою производительность. база данных, но я хочу убедиться, что мы используем лучшие практики и сосредоточены на производительности здесь.

1 6

1 ответ:

В 64-системе эти две таблицы почти идентичны. Столбец description_id в description_int занимает 8 байт (4 для целого числа и 4 для выравнивания). Попробуйте этот тест:

select 
    pg_relation_size('description_int')/10000000 as table_int, 
    pg_relation_size('description_bigint')/10000000 as table_bigint,
    pg_relation_size('description_int_pkey')/10000000 as index_int,
    pg_relation_size('description_bigint_pkey')/10000000 as index_bigint;

Средний размер строк обеих таблиц практически одинаков. Это происходит потому, что целочисленный столбец занимает 8 байт (4 байта для значения и 4 байта выравнивания) точно так же, как bigint (8 байт для значения без наполнителя). То же самое относится и к индексным записям. Однако это особый случай. Если мы добавим еще один целочисленный столбец к первая таблица:

CREATE TABLE two_integers
(
  description_id INT PRIMARY KEY NOT NULL,
  one_more_int INT,
  description VARCHAR(200),
  constraint description_id_positive CHECK (description_id >= 0)
);

Средний размер строки должен оставаться прежним.

Подробнее см. В разделе вычисление и экономия места в PostgreSQL.