Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kYIVS-00082s-6p for pgsql-hackers@arkaria.postgresql.org; Fri, 30 Oct 2020 00:43:02 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1kYIVR-0000aK-5a for pgsql-hackers@arkaria.postgresql.org; Fri, 30 Oct 2020 00:43:01 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kYIVQ-0000Zq-RR for pgsql-hackers@lists.postgresql.org; Fri, 30 Oct 2020 00:43:00 +0000 Received: from mail-ed1-x52f.google.com ([2a00:1450:4864:20::52f]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1kYIVN-0004Ip-OA for pgsql-hackers@lists.postgresql.org; Fri, 30 Oct 2020 00:42:59 +0000 Received: by mail-ed1-x52f.google.com with SMTP id p93so4904076edd.7 for ; Thu, 29 Oct 2020 17:42:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=6llrMKY7ztFTWrSMmpo3bYDDAhEgFdfOYvQJbQgcwvo=; b=V/XmBIooj3Ukr+8oE9lzFaARsOxlKyU9dCOxA9YENZppZFrfPr34/ZBfRCXnu1FAml qt2Y4BnJMOdojDmuMhQvCxw5au6a5h8LxqsSc8OuOi8cTpfM6TDqKh5wNrNtHD8taNNg dJlpTRs6l3v0wkB+8Ng0U8YRAFyvX8mYC7lh95qDw0ySIh/0W83xoRS4zg2rxQ6x3STx wWT+mPpB20NVcJ3/sJ/xUZViaYks6gMVS6yu/9dPamAs05/L0Ln/kT29Wx9R8+7O0AaO XIAvo7YDwr/9Wi6dxcEdbFO19U8G8hacjgYSNzwG1i3ZZaQYhwF1bb03mMofjgAR36VK JzyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=6llrMKY7ztFTWrSMmpo3bYDDAhEgFdfOYvQJbQgcwvo=; b=sin4EbTZkS5sylCMSf0n8ZpeX371SXhKXC9MvHP1MuvKLgXt8eCcOBmtSD0Xb5ib0J PjmW/hZw8RCFaCuAtIGm84csskYAt/2+Lr6u+c1W6yBxcVl01S/8BFZhIlgw/8r4c5Qj UUIIPzPUr/nA31UVzlit6y/Fbmkz4XyvED7M+lXa8PEMhIQXol00g6Ls4Q6MPeV+sJke XOZyN7PWmpI+diclf1XvLJM6QUIR8ZiqPk5RAOCGPFFFi2ncbVg+uYWLKwiWIVb109x+ Yv/xYKHzD9InEuIwQxuEOXtd6Kz7l7ZLMQqnQu1cyB4OYfEk12nKkjRwKQbHBOzUbEyX K0DA== X-Gm-Message-State: AOAM531UBgxfWChbdfQ6a6OIO5bICPEdBS7C4q3guORB3jNWuixo+FkO JcxvGlKpudfQCrdrSLifS+/CXw== X-Google-Smtp-Source: ABdhPJw3lKOEyrRicAm+14w6MGSj69QoKBUrsqXfCkamMoP6pfmvOvYCBdOn5VGvqlMDwSWJAAK5ZQ== X-Received: by 2002:a50:8ada:: with SMTP id k26mr6765451edk.281.1604018575967; Thu, 29 Oct 2020 17:42:55 -0700 (PDT) Received: from localhost (ip-86-49-245-76.net.upcbroadband.cz. [86.49.245.76]) by smtp.gmail.com with ESMTPSA id q22sm2279863ejm.13.2020.10.29.17.42.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Oct 2020 17:42:55 -0700 (PDT) Date: Fri, 30 Oct 2020 01:42:52 +0100 From: Tomas Vondra To: Tatsuo Ishii Cc: lubennikovaav@gmail.com, pgsql-hackers@lists.postgresql.org, pavan.deolasee@gmail.com, ibrar.ahmad@gmail.com Subject: Re: COPY FREEZE and setting PD_ALL_VISIBLE/visibility map bits Message-ID: <20201030004252.d63rwclys4bniluu@development> References: <160382617166.1204.475752573208579406.pgcf@coridan.postgresql.org> <20201028.144653.966121790856478893.t-ishii@sraoss.co.jp> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: <20201028.144653.966121790856478893.t-ishii@sraoss.co.jp> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, I might be somewhat late to the party, but I've done a bit of benchmarking too ;-) I used TPC-H data from a 100GB test, and tried different combinations of COPY [FREEZE] and VACUUM [FREEZE], both on current master and with the patch. The results look like this (the columns say what combination of COPY and VACUUM was used - e.g. -/FREEZE means plain COPY and VACUUM FREEZE) master: - / - FREEZE / - - / FREEZE FREEZE / FREEZE ---------------------------------------------------------------- COPY 2471 2477 2486 2484 VACUUM 228 209 453 206 patched: - / - FREEZE / - - / FREEZE FREEZE / FREEZE ---------------------------------------------------------------- COPY 2459 2445 2458 2446 VACUUM 227 0 467 0 So I don't really observe any measurable slowdowns in the COPY part (in fact there seems to be a tiny speedup, but it might be just noise). In the VACUUM part, there's clear speedup when the data was already frozen by COPY (Yes, those are zeroes, because it took less than 1 second.) So that looks pretty awesome, I guess. For the record, these tests were run on a server with NVMe SSD, so hopefully reliable and representative numbers. A couple minor comments about the code: 1) Maybe add a comment before the block setting xlrec->flags in heap_multi_insert. It's not very complex, but it used to be a bit simpler, and all the other pieces around have comments, so it won't hurt. 2) I find the "if (all_frozen_set)" block a bit strange. It's a matter of personal preference, but I'd just use a single level of nesting, i.e. something like this: /* if everything frozen, the whole page has to be visible */ Assert(!(all_frozen_set && !PageIsAllVisible(page))); /* * If we've frozen everything on the page, and if we're already * holding pin on the vmbuffer, record that in the visibilitymap. * If we're not holding the pin, it's OK to skip this - it's just * an optimization. * * It's fine to use InvalidTransactionId here - this is only used * when HEAP_INSERT_FROZEN is specified, which intentionally * violates visibility rules. */ if (all_frozen_set && visibilitymap_pin_ok(BufferGetBlockNumber(buffer), vmbuffer)) visibilitymap_set(...); IMHO it's easier to read, but YMMV. I've also reworded the comment a bit to say what we're doing etc. And I've moved the comment from inside the if block into the main comment - that was making it harder to read too. 3) I see RelationGetBufferForTuple does this: /* * This is for COPY FREEZE needs. If page is empty, * pin vmbuffer to set all_frozen bit */ if ((options & HEAP_INSERT_FROZEN) && (PageGetMaxOffsetNumber(BufferGetPage(buffer)) == 0)) visibilitymap_pin(relation, BufferGetBlockNumber(buffer), vmbuffer); so is it actually possible to get into the (all_frozen_set) without holding a pin on the visibilitymap? I haven't investigated this so maybe there are other ways to get into that code block. But the new additions to hio.c get the pin too. 4) In heap_xlog_multi_insert we now have this: if (xlrec->flags & XLH_INSERT_ALL_VISIBLE_CLEARED) PageClearAllVisible(page); if (xlrec->flags & XLH_INSERT_ALL_FROZEN_SET) PageSetAllVisible(page); IIUC it makes no sense to have both flags at the same time, right? So what about adding Assert(!(XLH_INSERT_ALL_FROZEN_SET && XLH_INSERT_ALL_VISIBLE_CLEARED)); to check that? 5) Not sure we need to explicitly say this is for COPY FREE in all the blocks added to hio.c. IMO it's sufficient to use HEAP_INSERT_FROZEN in the condition, at this level of abstraction. I wonder what to do about the heap_insert - I know there are concerns it would negatively impact regular insert, but is it really true? I suppose this optimization would be valuable even for cases where multi-insert is not possible. regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services