Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vFprQ-001pEq-18 for pgsql-general@arkaria.postgresql.org; Mon, 03 Nov 2025 08:24:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1vFprO-000s0I-Am for pgsql-general@arkaria.postgresql.org; Mon, 03 Nov 2025 08:24:17 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vFprN-000s0A-Vs for pgsql-general@lists.postgresql.org; Mon, 03 Nov 2025 08:24:17 +0000 Received: from mail-oo1-xc42.google.com ([2607:f8b0:4864:20::c42]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vFprK-005iFP-0d for pgsql-general@lists.postgresql.org; Mon, 03 Nov 2025 08:24:16 +0000 Received: by mail-oo1-xc42.google.com with SMTP id 006d021491bc7-654ecd8afafso996151eaf.2 for ; Mon, 03 Nov 2025 00:24:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762158252; x=1762763052; darn=lists.postgresql.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=e+8ZkM/ib6BFQqktLJwZGP45cnOkTIOvV0tg7xxuLR0=; b=TLsl2gyC42AbjTpuS9Gpyy+1QGF/5CgE2qPVkCDREUc30NaO6LU8YCB19y1DPxk91c pwgrKz9Yot4eynfwsFQvsdPR0+bwDFG3niCWf4jIJos8ha+yuAVOYoj7z2iGdJpan95U 4Qkxu+35d4lXcS6GhBCGs3M7Lg7vBSwWID2xZnXoz8t77iI9lZZCVs9sX5AH68NEemcs MTm5eghm90cLmElz6tnH/b92o/CoUcL0rUwXD1yhLzXSgCc/hsKCu+SnU5SshcIWa6OP TU5wfd7vwa1bYnFVrMpnwln64le4JAZyYp94fseLHVSSj3nGSt0CZWLykjHWsXBKCuZx YRTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762158252; x=1762763052; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=e+8ZkM/ib6BFQqktLJwZGP45cnOkTIOvV0tg7xxuLR0=; b=hKL2omIWrCL2vG8SJwQdB9Rcx6dwNaOOrvJgUge7cL4zNedR4ZgBvp7ehCdeCczOvi FXFo6ALgHGiU559A0EUZ3+sOSC1BRD8rH6gADPm2Z1G70gZCKcrRymMOfVqrAvG2E/1j wz64xtNkdSFeJ/WI73xKoXNrcbK0lJiIVuWen86uLITii39QQ6n62KBndYQYFiSWZcT0 zXvgmR3QrYi+JritiW7OeuQyN4+/WLRf3dEHNOuUAW8/+dPYpMnIzx26NmwP1UPhYDA/ c52EeXjjmWNKNwNXfJ/SmobY+T+OZZaBsu5HpKGW5iOIxq4Tv1q7IefqbBUdaH4UdkjO ZL9A== X-Gm-Message-State: AOJu0Yz18lbHrgvkWc/2jXW7nWBkPTQ/EmYW9pI8nR0P4K9nSrRtoVPn H9J2d2DCmckq47nJOqtBaq7MAETlklWfVbk38X29toPVL+/LPcpIuNmNI1ecR8zlzheU89gEkCs DAjxlel26nPQ+Y+BFzIfx3sBB3Dih4GtJCzJkZOo= X-Gm-Gg: ASbGnct8u6maKQsW/tuZyeTMrAiEpt/uHLNuZSoGnhJCbMrzz0hy+MqiWt4TNKcJL1d DLyFRKvUwMnD//4QSYMQTz1fnS8FzApyqNs5TLlS+NRVaMw+5nGtbJYY6lBDqHHbsg5mIfR/nrh fLPzkgD37GM6v15LBnKUl8XUeZjtmfjKGpb9CN5obvRV8IM2RvO+dPDtuWNEF1ssI+qCRrBtSvr 9um1+scTE4M25MTPF3vt+yXxWf93/C3noGGAovIe2XRYQ1FPKj+TJiVBNULLw== X-Google-Smtp-Source: AGHT+IE/eZ8zjDRJFD9lm8ncz/TkLmx4SYg2hJZkLMHUpBUgZBPZmiK7mGF7kxX2JFRwfvf3wePrQhZT1wMut5Ce9yY= X-Received: by 2002:a05:6820:1ca4:b0:651:c61b:8b21 with SMTP id 006d021491bc7-6568a6e1c01mr5345993eaf.3.1762158251601; Mon, 03 Nov 2025 00:24:11 -0800 (PST) MIME-Version: 1.0 From: Marcelo Fernandes Date: Mon, 3 Nov 2025 21:24:00 +1300 X-Gm-Features: AWmQ_bmyRPz96-BcSe82omRr2VgV3VvfZ3plHyn6ykIs9aFvziGatLOPP25yuCo Message-ID: Subject: Increasing a NUMERIC column precision doesn't cause a table rewrite. Why? To: pgsql-general@lists.postgresql.org Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi everyone, A numeric field is defined as: NUMERIC(precision, scale) [0]. After doing some playing around with different operations against a numeric column, namely: increasing/decreasing the precision or increasing/decreasing the scale, I noticed that the table is rewritten in all cases except when increasing the precision number. Take the following snippet as example (tested on postgres 15): ```sql CREATE DATABASE test_precision_field; -- \c test_precision_field SET client_min_messages=debug1; DROP TABLE IF EXISTS foo; CREATE TABLE foo (id SERIAL PRIMARY KEY, bar NUMERIC(10, 2)); -- Only increase precision but keep the scale: -- This does not rewrite the table ALTER TABLE foo ALTER COLUMN bar TYPE numeric(20, 2); -- Only decrease the precision but keep the scale: -- This rewrites the table. ALTER TABLE foo ALTER COLUMN bar TYPE numeric(10, 2); -- DEBUG: rewriting table "foo" -- DEBUG: building index "foo_pkey" on table "foo" serially -- DEBUG: index "foo_pkey" can safely use deduplication -- Only increase the scale, but keep the precision: -- This rewrites the table. ALTER TABLE foo ALTER COLUMN bar TYPE numeric(10, 4); -- DEBUG: rewriting table "foo" -- DEBUG: building index "foo_pkey" on table "foo" serially -- DEBUG: index "foo_pkey" can safely use deduplication -- Only decrease the scale, but keep the precision: -- This rewrites the table. ALTER TABLE foo ALTER COLUMN bar TYPE numeric(10, 2); -- DEBUG: rewriting table "foo" -- DEBUG: building index "foo_pkey" on table "foo" serially -- DEBUG: index "foo_pkey" can safely use deduplication ``` My assumption is that once the precision is increased, Postgres can still interpret the old values that were generated with a lower precision, whereas this is not possible for any other types of changes on the numeric field. Is that assumption correct? How can I verify it? For example, is there a catalog table I can have a look to see how these values are defined, along with some form of documentation to understand how they are interpreted by Postgres? Thank you, Marcelo. - [0] https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL