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 1vFwyw-0047z4-AV for pgsql-general@arkaria.postgresql.org; Mon, 03 Nov 2025 16:00:33 +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 1vFwyv-005R6B-7S for pgsql-general@arkaria.postgresql.org; Mon, 03 Nov 2025 16:00:32 +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 1vFwyu-005R62-2q for pgsql-general@lists.postgresql.org; Mon, 03 Nov 2025 16:00:31 +0000 Received: from fout-b6-smtp.messagingengine.com ([202.12.124.149]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vFwyp-005lt8-2S for pgsql-general@lists.postgresql.org; Mon, 03 Nov 2025 16:00:30 +0000 Received: from phl-compute-11.internal (phl-compute-11.internal [10.202.2.51]) by mailfout.stl.internal (Postfix) with ESMTP id 8652B1D002CB; Mon, 3 Nov 2025 11:00:25 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-11.internal (MEProxy); Mon, 03 Nov 2025 11:00:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= cc:content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm2; t=1762185625; x=1762272025; bh=hJ6DeY1fd3jS7skAkO+KqWiUiT8wNXnRV0sSp9ksW0E=; b= S2/kIacW1362ukiiHHmIeNrrR4eMb24u5a7lLSOTcX43xDR8gBzizkFrcyJZWxtd +4738aGL4GWJ8kCtyhFVXwvo5DEOCC6Z5ErL17q5eQaD38IuTo92vNJ0PJmbQkk2 csf3ZCQiQwMPeFdAxNqKidvWW6MeEwp4OOHp8/Z4gVa2/JK/LfLfi2ifowaHDmYP NK5NwDNp77Gt+2R1WEpRljuVyLmCq3HwGVP554m56AYmvsx4Zerw/q2t7AloFGDl 6L2AczNj0zS/KGop/e8Q3aoB1+iOn2WQbb+R48NQoizEJcLriqIvPBQfrHyzovDm zu2cnymr5nI0oUj7VPuVgw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1762185625; x=1762272025; bh=h J6DeY1fd3jS7skAkO+KqWiUiT8wNXnRV0sSp9ksW0E=; b=NaEBRCweIVcV5Yl/J T34HeWMkkJc8VLo/MotAwb4QAyp5bwb/mNVjyll0zHss2EqoGWLxmII9bhNWira0 m3oCwebIELf3icERwijWze4BvdRmvNICLMdmCrwkqQEUkSRWRh8GQNady75MkOTi tC+ZwWP5zHxk58TCd1s9FF0Od+uYzhElM3ktpT8VmTKF7jAW7C7/BtsL4xPSRwdO 0DWhqYtdVNF9kAZjgJwvSAE2Z2CQ3Dy/iRHkSmt7Bga6RQm2B4qQF4bW79MBT512 HSDat7cSYP1WEa9FX+/B3MEOLwPj3L/8D5goN4FIrM/YHXVFSjd04ADErUqEsi9/ FXOcA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddujeekheehucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepkfffgggfuffvfhfhjggtgfesthejredttddvjeenucfhrhhomheptegurhhirghn ucfmlhgrvhgvrhcuoegrughrihgrnhdrkhhlrghvvghrsegrkhhlrghvvghrrdgtohhmqe enucggtffrrghtthgvrhhnpeefkedukeetvedugeffvddujeethfeigfeuheetfefhudel vddtieevuddvteefvdenucffohhmrghinhepphhoshhtghhrvghsqhhlrdhorhhgpdhgih hthhhusgdrtghomhenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhl fhhrohhmpegrughrihgrnhdrkhhlrghvvghrsegrkhhlrghvvghrrdgtohhmpdhnsggprh gtphhtthhopedvpdhmohguvgepshhmthhpohhuthdprhgtphhtthhopehmrghrtggvfhgv rhhnjeesghhmrghilhdrtghomhdprhgtphhtthhopehpghhsqhhlqdhgvghnvghrrghlse hlihhsthhsrdhpohhsthhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i76984098:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 3 Nov 2025 11:00:24 -0500 (EST) Message-ID: <343aed61-3bcf-4ed9-a1e8-1aa2547624b8@aklaver.com> Date: Mon, 3 Nov 2025 08:00:24 -0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Increasing a NUMERIC column precision doesn't cause a table rewrite. Why? To: Marcelo Fernandes , pgsql-general@lists.postgresql.org References: Content-Language: en-US From: Adrian Klaver In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 11/3/25 00:24, Marcelo Fernandes wrote: > 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? Short version: https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL " Numeric values are physically stored without any extra leading or trailing zeroes. Thus, the declared precision and scale of a column are maximums, not fixed allocations. (In this sense the numeric type is more akin to varchar(n) than to char(n).) The actual storage requirement is two bytes for each group of four decimal digits, plus three to eight bytes overhead. " Long version, numeric.c: https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/numeric.c > > Thank you, > Marcelo. > > - [0] https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL > > -- Adrian Klaver adrian.klaver@aklaver.com