[IMP] base: reduce new DB size by ordering columns
Postgres is aligning columns to 4 or 8 bytes, depending on their type.
So, consecutive fixed-length columns of differing size will be padded
with empty bytes due to the alignment requirements.
Before this patch, columns where created in their definition order. Now,
they are ordered based on their size, in order to minimize the padding.
As an example, before each row uses 36 bytes (+24b header):
attname | typname | typlen
-------------+-----------+--------
id | int4 | 4
create_uid | int4 | 4
create_date | timestamp | 8
write_uid | int4 | 4 -> 4 bytes padding
write_date | timestamp | 8
active | bool | 1 -> 3 bytes padding
After each row uses 32 bytes (4 bytes saved per row):
attname | typname | typlen
-------------+-----------+--------
id | int4 | 4
create_uid | int4 | 4
write_uid | int4 | 4
active | bool | 1 -> 3 bytes padding
create_date | timestamp | 8
write_date | timestamp | 8
This saving scheme applies to all rows in all tables. We save between 4
and 8 bytes per row just on the usual create_uid, create_date,
write_uid, write_date.
closes odoo/odoo#87896
Signed-off-by: Raphael Collet <rco@odoo.com>
This commit is contained in:
committed by
Raphael Collet
parent
abd50a5ccb
commit
e045e76e35
@@ -6,6 +6,7 @@
|
||||
import logging
|
||||
import psycopg2
|
||||
import odoo.sql_db
|
||||
from collections import defaultdict
|
||||
from contextlib import closing
|
||||
|
||||
_schema = logging.getLogger('odoo.schema')
|
||||
@@ -50,6 +51,17 @@ def table_kind(cr, tablename):
|
||||
cr.execute(query, (tablename,))
|
||||
return cr.fetchone()[0] if cr.rowcount else None
|
||||
|
||||
# prescribed column order by type size: 4 bytes, 1 byte, 8 bytes, variable size
|
||||
# (values have been chosen to minimize padding in rows; unknown column types
|
||||
# are considered variable size and put last)
|
||||
SQL_ORDER_BY_TYPE = defaultdict(lambda: 6, {
|
||||
'int4': 1, # 4 bytes
|
||||
'date': 2, # 4 bytes
|
||||
'bool': 3, # 1 byte
|
||||
'float8': 4, # 8 bytes
|
||||
'timestamp': 5, # 8 bytes
|
||||
})
|
||||
|
||||
def create_model_table(cr, tablename, comment=None, columns=()):
|
||||
""" Create the table for a model. """
|
||||
colspecs = ['id SERIAL NOT NULL'] + [
|
||||
|
||||
Reference in New Issue
Block a user