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 1shZXR-004AJQ-Pl for pgsql-hackers@arkaria.postgresql.org; Fri, 23 Aug 2024 19:01: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 1shZXP-00GJ9N-GN for pgsql-hackers@arkaria.postgresql.org; Fri, 23 Aug 2024 19:01:32 +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.94.2) (envelope-from ) id 1shZXP-00GJ9F-0k for pgsql-hackers@lists.postgresql.org; Fri, 23 Aug 2024 19:01:31 +0000 Received: from mail-ot1-x330.google.com ([2607:f8b0:4864:20::330]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1shZXM-0016V8-MJ for pgsql-hackers@lists.postgresql.org; Fri, 23 Aug 2024 19:01:30 +0000 Received: by mail-ot1-x330.google.com with SMTP id 46e09a7af769-70e00cb1ee7so1697506a34.1 for ; Fri, 23 Aug 2024 12:01:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1724439687; x=1725044487; darn=lists.postgresql.org; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:from:to:cc:subject:date :message-id:reply-to; bh=S3DoHIDjhrMHtXSoKceMmbzivBXQRt9IPjIeDz/rbMw=; b=erpvN2AFxeGBfgDe+U2nguV21AOOaw+8P+PuQfhufkjIMU/pL7QWve7NvFU0KouUtz aQJr3rXuzl9UB8gWjya06o6pj/7TkdlAvBa587Q6bamzVjC7ialHKpcHkU0tuT5qs6sU kEXB144J7mVaDwjTn+2GGTJ3o2bRkkgPCrYL0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724439687; x=1725044487; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S3DoHIDjhrMHtXSoKceMmbzivBXQRt9IPjIeDz/rbMw=; b=MeYJh5oHZgUpPUyJJMgNzpRzhE70aZX0D1sXJWxLW+pI9lI5NI4h6mA4Ri0nmCuyVB VrRZrgx7XMqulK1gEdtvdfBJJoFsBIq30dwP+WIPWLaPM0mGByF2bMaDDeAIlvRADYVy 5HgW2Y8ehk/m69z6c7wyHCeyw92sXG//uz4L0/fXAwYybQOYp0UyEbaPotnXJ34vzEBs zIu59EVrIS3rtrW+DZgoCDgR1l+0uwb7SC6r7ECc6tUNTjEG5kDt1m46ve8Ix/SHLZeS CiKgQno1V7vuZ0j37bcbDrrF9H0S0kN2r+giHAl8uJXZ3aDoXQsJpUWvdrYV88hDYPmi 3HZg== X-Gm-Message-State: AOJu0YxlkF3F1eyFh3Tnpi23JqjgdMsw/l2fWoiD0uov6HiX4YQ0Kf32 YJP6VLgXvBTMz61CLNHnJ3mIuV/KIwvHjr2cAEtpRQG6K7r+ZeqjT9HJAs30XOP1r+Q6Y8wN3e8 = X-Google-Smtp-Source: AGHT+IFptDf/JVGldaXWjwOoQD+sTKVNXDElWwFOZ94T9i4WPhNi4CEvHYeKbvg4qxklZJp85hWhyA== X-Received: by 2002:a05:6808:3094:b0:3d9:3e48:8af7 with SMTP id 5614622812f47-3de2a8afda3mr3597008b6e.40.1724439687290; Fri, 23 Aug 2024 12:01:27 -0700 (PDT) Received: from rfd.leadboat.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id 5614622812f47-3de225c5322sm822002b6e.42.2024.08.23.12.01.26 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 23 Aug 2024 12:01:26 -0700 (PDT) Date: Fri, 23 Aug 2024 12:01:24 -0700 From: Noah Misch To: Nazir Bilal Yavuz Cc: PostgreSQL Hackers Subject: Re: Use read streams in pg_visibility Message-ID: <20240823190124.9e@rfd.leadboat.com> References: <20240820184742.f2.nmisch@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Fri, Aug 23, 2024 at 02:20:06PM +0300, Nazir Bilal Yavuz wrote: > On Tue, 20 Aug 2024 at 21:47, Noah Misch wrote: > > On Tue, Aug 13, 2024 at 03:22:27PM +0300, Nazir Bilal Yavuz wrote: > > > The downside of this approach is there are too many "vmbuffer is valid > > > but BufferGetBlockNumber(*vmbuffer) is not equal to mapBlock, so > > > vmbuffer needs to be read again" cases in the read stream version (700 > > > vs 20 for the 6 GB table). This is caused by the callback function of > > > the read stream reading a new vmbuf while getting next block numbers. > > > So, vmbuf is wrong when we are checking visibility map bits that might > > > have changed while we were acquiring the page lock. > > > > Did the test that found 700 "read again" use a different procedure than the > > one shared as setup.sh down-thread? Using that script alone, none of the vm > > bits are set, so I'd not expect any heap page reads. > > Yes, it is basically the same script but the query is 'SELECT > pg_check_visible('${TABLE}'::regclass);'. I gather the scripts deal exclusively in tables with no vm bits set, so pg_visibility did no heap page reads under those scripts. But the '700 "read again"' result suggests either I'm guessing wrong, or that result came from a different test procedure. Thoughts? > > The "vmbuffer needs to be read again" regression fits what I would expect the > > v1 patch to do with a table having many vm bits set. In general, I think the > > fix is to keep two heap Buffer vars, so the callback can work on one vmbuffer > > while collect_corrupt_items() works on another vmbuffer. Much of the time, > > they'll be the same buffer. It could be as simple as that, but you could > > consider further optimizations like these: > > Thanks for the suggestion. Keeping two vmbuffers lowered the count of > "read-again" cases to ~40. I ran the test again and the timing > improvement is ~5% now. > I think the number of "read-again" cases are low enough now. Agreed. The increase from 20 to 40 is probably an increase in buffer mapping lookups, not an increase in I/O. > Does creating something like > pg_general_read_stream_next_block() in read_stream code and exporting > it makes sense? To me, that name isn't conveying the function's behavior, and the words "pg_" and "general_" aren't adding information there. How about one of these names or similar: seq_read_stream_cb sequential_read_stream_cb block_range_read_stream_cb > > The callback doesn't return blocks having zero vm bits, so the blkno variable > > is not accurate. I didn't test, but I think the loop's "Recheck to avoid > > returning spurious results." looks at the bit for the wrong block. If that's > > what v1 does, could you expand the test file to catch that? For example, make > > a two-block table with only the second block all-visible. > > Yes, it was not accurate. I am getting blockno from the buffer now. I > checked and confirmed it is working as expected by manually logging > blocknos returned from the read stream. I am not sure how to add a > test case for this. VACUUM FREEZE makes an all-visible, all-frozen table. DELETE of a particular TID, even if rolled back, clears both vm bits for the TID's page. Past tests like that had instability problems. One cause is a concurrent session's XID or snapshot, which can prevent VACUUM setting vm bits. Using a TEMP table may have been one of the countermeasures, but I don't remember clearly. Hence, please search the archives or the existing pg_visibility tests for how we dealt with that. It may not be problem for this particular test. > There is one behavioral change introduced with the patches. It could > happen when collect_corrupt_items() is called with both all_visible > and all_frozen being true. > -> Let's say VM_ALL_FROZEN() returns true but VM_ALL_VISIBLE() returns > false in callback. Callback returns this block number because > VM_ALL_FROZEN() is true. > -> At the /* Recheck to avoid returning spurious results. */ part, we > should only check VM_ALL_FROZEN() again as this was returning true in > the callback. But we check both VM_ALL_FROZEN() and VM_ALL_VISIBLE(). > VM_ALL_FROZEN() returns false and VM_ALL_VISIBLE() returns true now > (vice versa of callback). > -> We were skipping this block in the master but the patched version > does not skip that. > > Is this a problem? If this is a problem, a solution might be to > callback return values of VM_ALL_FROZEN() and VM_ALL_VISIBLE() in the > per_buffer_data. No, I don't consider that a problem. That's not making us do additional I/O, just testing more bits within the pages we're already loading. The difference in behavior is user-visible, but it's the same behavior change the user would get if the timing had been a bit different.