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.96) (envelope-from ) id 1w6WH2-004Nex-1F for pgsql-hackers@arkaria.postgresql.org; Sat, 28 Mar 2026 16:12:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w6WGz-00Ego6-2C for pgsql-hackers@arkaria.postgresql.org; Sat, 28 Mar 2026 16:12:30 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w6WGz-00Egnx-0e for pgsql-hackers@lists.postgresql.org; Sat, 28 Mar 2026 16:12:29 +0000 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w6WGx-00000001W0u-0RSI for pgsql-hackers@lists.postgresql.org; Sat, 28 Mar 2026 16:12:28 +0000 Received: by mail-wr1-x430.google.com with SMTP id ffacd0b85a97d-43ccda008cdso502401f8f.0 for ; Sat, 28 Mar 2026 09:12:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1774714341; cv=none; d=google.com; s=arc-20240605; b=bUjYfWBee2jtOi2Ipr8xaglIDQgvxFnkggvZLfMTh1ZBwdNViD1phJcbJ4XR1DVUWJ wzLfvGrrAKDAmiWw9nH5/M5jh7ccurH4Rgs6TR+iuGjVBvzEf1GtbCZXuHYJ0SZmlKh8 xdtpKStIOGfoDVkH5LDO/X0CWoMPPh3rIabIeGKXkCeq+XRBKX7o4UNPOHp2sVaAhtot ML8YLES2u0LToq+JfPIMxd9FvYMneaw/5HF8au0Ktg1TmrwvZf/OfQS1R2R9GZUgVx8Q oqIj8Qhd+/3p88j74M5c0Nf+0/1qxXWC6ZOxikH1HEyMqBz+sO4uYl60H0kBFnSu4w11 vbiw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=m1p5LicfR6l9Sark3yBpkZiBYcc8GQhtm3q/J4/yksg=; fh=GdlhGiHvYR3KmESld/UgCsB/codnQWSfnfVNmIk9tu8=; b=VsX83dvVcrXd02Dnn8RuN1os/R4X8gD/SYIXkPiv3TlqeDwcSoGprZRwo9o8wzOpKj kgngzIwoam2pkJUams0diV42giFb/9Y51GffLC9zDV0vBhgLFcSJc0CUjA5Py9WOSewJ knub8YiHZgWbI80JhxmnKBopYu5w+uVtY2eNKXDCi6sCr6Mk7NMp9++Ol8IoX2Z37X0W r22rEEO5GyQY59k7SaCkzn6uXxCiUCbU1F0h84YLHH8AS5/1oa3cKYZaaKXeZ1dq7okU 0hhwX+xdHVkHCW+1j+evoZfhjCussIVdgdtpGKnbZqESV1L09AxhUH4KIJq1ijwgKdEr zeiQ==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774714341; x=1775319141; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=m1p5LicfR6l9Sark3yBpkZiBYcc8GQhtm3q/J4/yksg=; b=ciP/MNLHrzt8Bad4X5uvG4yer9llcNScsG+pX6307/QjQ0e/r++mQ21Ez6AzehKmE+ UFa4h5f19M0RXHd4icCyUNTnnKkVyt1L1uo9kBgiPiMeou3rwm8/Tsipnvkgr9NJu0xp Lrpu2Kdc0J2l4ckYl4KCrrsAVmXtr+JxcregvA4nkJFLvoZZj1Kwla4y923Ze1eKFALD oqMNH/KpXhjE2pshrnQ15bDmvKYP8yi9WmHW3EQeoC8EQhGMRDRM63W5MN7+/H2bxfl+ dqQmaW/FyKbvtqaM8aIGQ4Q9ISdbDQnoA4mo63vfCWhsqaxtzbikfrJL5T7tapvpgRez Vydg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774714341; x=1775319141; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=m1p5LicfR6l9Sark3yBpkZiBYcc8GQhtm3q/J4/yksg=; b=R54ONWF5+Ou4XffFDOkLi+Bq6N2MpBX9hitoxp0BmJ8VrwcvLE5lHD7NzKBVNlM99T R+j1POwm3DTCS9cKkVYmcHyy9td+xhizKfkfEODtytr2xhOQCxE24pM5ZN2U6RK+m9ng phOwhgqvhbTQZl3Z/0QpM+tLIZXn8FYs3OakN53tWp5aJehY52WtE53UcbXuGkRRWhMr vxigoKpHH5e1QfZvuMI/ZaM2Nm9TKW1fXNcdg0AHQICWffmn6BBr3C5lz4N8FMGmo+9H MCNukmHoyU/2ayImrqj36rpN1DG0hc7NgtDOxFXL+Y9RCz1nn6OjVcmtBHjNOy3pWAmW edhw== X-Forwarded-Encrypted: i=1; AJvYcCVX4elStXaRNXoGKx3aEbEL4Hjtv0691BSkeuJARB3mwZJAl1ZBcQo6gFiCouWm+RgKX/WTk6/4WFkia9OE@lists.postgresql.org X-Gm-Message-State: AOJu0YyKTlarnhyEjJIAEBBj8Z6endnad1gjNvAqa2aycVIojuXUA6im 5xr/pxCnLx30Nklsm7hpJQipoJYMXKMPAMa7G6P/oZJPaAN3iAyu1jbqcsLSGAhXuSn/zCQEHrw i2Eb7oZTj05arh0TM0KYgW83qpOaQ5RY= X-Gm-Gg: ATEYQzxNLFeRDjl2/DsnRhMegUJqJhGoNtr+ZgfM29vpaHWZJZ6gASo2lzP5MGuwSU+ mdSMxhOoI0XrsxhKdZhzrG1Y+JJbDX7Qw5Ztd3xligobnO4nyUGGWdcMuh3k6STiPasydR/1DEA B/7zW2jYATsSreqIuzpEdBui3I1EiBe4LkN2tvKi98NvT2SiQK7dUDofTWL3x4rWlKITg+SQyeL AKjvYOWckqEwS0g+A5wxw6FcyGg3Y4KG1UeN6zylOApxy9TCs0nbVH5c6H8XvmLKZs7LOcN6NSR DSK0AJ9skCx/0/h28PN6iOXRexey5POh42Rz+KIWlE554Slgk5g= X-Received: by 2002:a05:6000:2c06:b0:43b:4312:2cbb with SMTP id ffacd0b85a97d-43b9eb10dc5mr10287095f8f.17.1774714340360; Sat, 28 Mar 2026 09:12:20 -0700 (PDT) MIME-Version: 1.0 References: <670b867e-6518-48b0-b7c2-bd5f10ab58c6@vondra.me> In-Reply-To: From: Ashutosh Bapat Date: Sat, 28 Mar 2026 21:42:07 +0530 X-Gm-Features: AQROBzBEk8F8af3g3clZBDUReGHw26-F5oLZxHlVJMyp0JS5Ei4dil3T4lZSxrA Message-ID: Subject: Re: pg_buffercache: Add per-relation summary stats To: Masahiko Sawada Cc: Tomas Vondra , Lukas Fittl , PostgreSQL Hackers , Paul A Jungwirth , Khoa Nguyen Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Sat, Mar 28, 2026 at 11:07=E2=80=AFAM Masahiko Sawada wrote: > > On Fri, Mar 27, 2026 at 3:58=E2=80=AFPM Tomas Vondra wr= ote: > > > > On 3/26/26 05:21, Ashutosh Bapat wrote: > > > On Wed, Mar 25, 2026 at 10:19=E2=80=AFPM Masahiko Sawada wrote: > > >> > > >> On Tue, Mar 24, 2026 at 11:47=E2=80=AFPM Lukas Fittl wrote: > > >>> > > >>> Hi Ashutosh, > > >>> > > >>> On Tue, Mar 24, 2026 at 11:24=E2=80=AFPM Ashutosh Bapat > > >>> wrote: > > >>>> I know we already have a couple of hand-aggregation functions but = I am > > >>>> hesitant to add more of these. Question is where do we stop? For > > >>>> example, the current function is useless if someone wants to find = the > > >>>> parts of a relation which are hot since it doesn't include page > > >>>> numbers. Do we write another function for the same? Or we add page > > >>>> numbers to this function and then there's hardly any aggregation > > >>>> happening. What if somebody wanted to perform an aggregation more > > >>>> complex than just count() like average number of buffers per relat= ion > > >>>> or distribution of relation buffers in the cache, do they write > > >>>> separate functions? > > >>> > > >>> I think the problem this solves for, which is a very common questio= n I > > >>> hear from end users, is "how much of this table/index is in cache" = and > > >>> "was our query slow because the cache contents changed?". > > >>> > > >>> It can't provide a perfect answer to all questions regarding what's= in > > >>> the cache (i.e. it won't tell you which part of the table is cached= ), > > >>> but its in line with other statistics we do already provide in > > >>> pg_stat_user_tables etc., which are all aggregate counts, not furth= er > > >>> breakdowns. > > >>> > > >>> Its also a reasonable compromise on providing something usable that > > >>> can be shown on dashboards, as I've seen in collecting this > > >>> information using the existing methods from small production system= s > > >>> in practice over the last ~1.5 years. > > >> > > >> Regarding the proposed statistics, I find them reasonably useful for > > >> many users. I'm not sure we need to draw a strict line on what belon= gs > > >> in the module. If a proposed function does exactly what most > > >> pg_buffercache users want or are already writing themselves, that is > > >> good enough motivation to include it. > > >> > > >> I think pg_visibility is a good precedent here. In that module, we > > >> have both pg_visibility_map() and pg_visibility_map_summary(), even > > >> though we can retrieve the exact same results as the latter by simpl= y > > >> using the former: > > >> > > >> select sum(all_visible::int), sum(all_frozen::int) from > > >> pg_visibility_map('test') ; > > >> > > > > > > A summary may still be ok, but this proposal is going a bit farther, > > > it's grouping by one subset which should really be done by GROUP BY i= n > > > SQL. And I do > > > > > > I am afraid that at some point, we will start finding all of these to > > > be a maintenance burden. At that point, removing them will become a > > > real pain for the backward compatibility reason. For example > > > 1. The proposed function is going to add one more test to an already > > > huge testing exercise for shared buffers resizing. > > > 2. If we change the way to manage buffer cache e.g. use a tree based > > > cache instead of hash + array cache, each of the functions which > > > traverses the buffer cache array is going to add work - adjusting it > > > to the new data structure - and make a hard project even harder. In > > > this case we have other ways to get the summary, so the code level > > > scan of buffer cache is entirely avoidable. > > > > > > If I am the only one opposing it, and there are more senior > > > contributors in favour of adding this function, we can accept it. > > > > > > > I understand this argument - we have SQL, which allows us to process th= e > > data in a flexible way, without hard-coding all interesting groupings. > > The question is whether this particular grouping is special enough to > > warrant a custom *faster* function. Well-said. Thanks. > > > > The main argument here seems to be the performance, and the initial > > message demonstrates a 10x speedup (2ms vs. 20ms) on a cluster with > > 128MB shared buffers. Unless I misunderstood what config it uses. > > > > I gave it a try on an azure VM with 32GB shared buffers, to make it a > > bit more realistic, and my timings are 10ms vs. 700ms. But I also wonde= r > > if the original timings really were from a cluster with 128MB, because > > for me that shows 0.3ms vs. 3ms (so an order of magnitude faster than > > what was reported). But I suppose that's also hw specific. > > > > Nevertheless, it is much faster. I haven't profiled this but I assume > > it's thanks to not having to write the entries into a tuplestore (and > > possibly into a tempfile). > > > > But is it actually needed / worth it? I wonder what timings does Lukas > > observe when running this on larger clusters. Because in a later email > > he says: > > > > ... we currently run this on a 10 minute schedule when enabled, and > > that seems to work in terms of understanding large swings in cache > > contents. > > > > I'm all in for optimizing stuff, but if you're running a monitoring tas= k > > every 10 minutes, does it matter if it's running for 1 or 5 seconds? I > > find that a bit hard to believe. > > I imagined such a query is just one of many monitoring queries running > concurrently, so the cumulative overhead can still matter. > What kind of cumulative overhead, do you see? Reduced TPS, increased memory/CPU consumption? I think itd will be good to see some metric evidence of this, rather than relying on the assumption. > > I don't have a clear opinion if we should do this. I kinda doubt it's a > > significant maintenance burden. It'd add one more place the patch for > > on-line resizing of shared buffers needs to worry about. Surely that > > should not be very difficult, considering there are ~5 other places in > > this very extension doing this already? > > Yeah, I've not looked at the online shared buffer resizing patch, but > I hope that the patch somewhat abstructs the access to shared buffers > that might be being resized so that we don't need to worry about the > complex part when writing code accessing the shared buffers. The code to abstract isn't there in the patch yet, but I agree that regular scan code shouldn't receive a lot of changes in the resizing implementation patch. I have been toying with the idea that we provide an abstraction to walk the buffer cache (foreach_buffer for example), which may hide any complexity, if required. So, yes, there will be some abstraction as you envision. However, testing will still be required. It's the testing effort, increase in test time etc. which I am worried about. However, I may be overestimating it. > > > One thing we lose by doing ad hoc aggregation (instead of just relying > > on the regular SQL aggregation operators) is lack of memory limit. > > There's a simple in-memory hash table, no spilling to disk etc. The > > simple pg_buffercache view does not have this issue, because the > > tuplestore will spill to disk after hitting work_mem. Simplehash won't. > > > > The entries are ~48B, so there would need to be buffers for ~100k > > (relfilenode,forknum) combinations to overflow 4MB. It's not very > > common, but I've seen systems with more relations that this. Would be > > good to show some numbers showing it's not an issue. > > Good point. I agree that we should not introduce the function in a way > that there is a risk of using excessive memory while not respecting > work_mem or other GUC parameters. +1. --=20 Best Wishes, Ashutosh Bapat