2016-06-27 3 views
2

Je veux augmenter mes performances de base de données. Dans un projet, toutes les tables sont passées de int à bigint, ce qui est un mauvais choix non seulement pour le stockage, car int requiert 4 bytes, et bigint requiert 8 bytes, mais aussi les performances. Je créé une petite table avec 10 millions entrées, avec un script dans Python:Benchmark: bigint vs int sur PostgreSQL

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)) 

Et voilà comment je créé mes two tables:

-- 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) 
); 

Après avoir inséré toutes ces données, je faire une requête pour les deux tables, pour mesurer la différence entre elles. Et pour ma grande surprise, ils ont tous deux les mêmes performances:

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

que je fais quelque chose de mal avec mon indice de référence? Ne devrait pas int être plus rapide que bigint? Surtout, lorsque le primary key est par définition un index ce qui signifie, pour créer un index pour bigint serait plus lent de créer un index pour int, avec la même quantité de données, non? Je sais que ce n'est pas seulement une petite chose qui aura un impact énorme sur les performances de ma base de données, mais je veux m'assurer que nous utilisons les meilleures pratiques et que nous nous concentrons sur les performances ici.

Répondre

8

Dans un système 64, les deux tables sont presque identiques. La colonne description_id dans description_int couvre 8 octets (4 pour l'entier et 4 pour l'alignement). Essayez ce test:

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; 

La taille moyenne des lignes des deux tables est pratiquement la même. En effet, la colonne entière occupe 8 octets (4 octets pour une valeur et 4 octets d'alignement) exactement comme bigint (8 octets pour une valeur sans remplissage). La même chose s'applique aux entrées d'index. C'est un cas particulier cependant. Si nous ajoutons une colonne entière supplémentaire à la première table:

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) 
); 

la taille moyenne des lignes doit rester la même.

Plus d'informations à Calculating and saving space in PostgreSQL.

+0

Salut @klin, j'ai obtenu ce résultat '76; 76; 22; 22'; Cela vous dérangerait-il de le clarifier? –

+0

Merci @klin! –

+0

@klin Vous semblez utiliser le mot "bits" au lieu de "octets" dans de nombreux endroits. – YeB