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 1paKXA-0003rZ-F3 for pgsql-hackers@arkaria.postgresql.org; Thu, 09 Mar 2023 17:58:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1paKX8-0001me-IX for pgsql-hackers@arkaria.postgresql.org; Thu, 09 Mar 2023 17:58:30 +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 1paKX7-0001mV-S0 for pgsql-hackers@lists.postgresql.org; Thu, 09 Mar 2023 17:58:30 +0000 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1paKX0-0008Hd-TY for pgsql-hackers@lists.postgresql.org; Thu, 09 Mar 2023 17:58:28 +0000 Received: by mail-wr1-x434.google.com with SMTP id t15so2736460wrz.7 for ; Thu, 09 Mar 2023 09:58:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb.com; s=google; t=1678384701; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=VktMuuATevIvW+GXznF3J1pk0GDJkBLgzkQLLtylB2Y=; b=kvQFWd8W/UYYLHIxh2aHRObJe+GrnLXwlJyB1dIQYAkGq0XfnEtL8zujSF7sFMKYFe fTJVE6MFjuDic7JPEWijxd1rcJNO2nHZYGOgQiFlfZ37dFbQkKESuFIdYullgwCogmCn IChpI6tog2d1letebObwmC4hNVI2CCPepND9pBrYr4d3wmyfvv/uKN2/LXMOUO4+J+H0 3OMnUoWQQcNFdC7Duoiiu+ELNbPBNgnvTju3xkKF2SxbF2wB7oNKeObF1e0thKxhxd7J MkGvHeSkXlbJoTSFfUiNyNAj1wsclkIDOhM5VWAKZxTd8H8aOb+8iiKE3a6sTSBbFXS7 uibg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678384701; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VktMuuATevIvW+GXznF3J1pk0GDJkBLgzkQLLtylB2Y=; b=vTHPXapqeqYJvTnG6/vC5PLdP3TAzETAz7+DH/Q+Qg++Tzv3GH4yGbjU32PjOj2YS7 aXHnxE4b4l0PGgV8vTYI+4hhSg9rmEHZRSoEjf9kW2VBfOWXJNkz52wAjyaHf4/TwSNQ Q++Yrj9SZ48DFEy/stxqEsQ4E7Y7tQD9TZTRPrBHUbamv7g3tivx05k4dOcP08cdUR3O dn0NGjSbXSvqxJH/rRZ8heAAldnjC0/5VXe3IbezdBQK8XvyeVoUkbo/lHH0HsgjAjEa VxrgKLAzYcoF/EaEYh2hJxZ2HrIcUqmCM0hX+0bGeth2vvUvRT2Hj02pKhrYvzS4iNBZ Mr3A== X-Gm-Message-State: AO0yUKVVxKN+KYf5p5OcVT2YROtg0CnDDx0QkxIGfeyxTqPBjkZqZcfx trmlBvyOnhVxASocLSo6Z0fsy25X2U6BIoP2K9uc/iEylxuhL2iXV+vjchzRXaK6UgCrEAEq/BL wvUwz14FYtcf0sUHsL6pyfd4vZzpY5+6/KbwoJlynK3M4Q5Lj3gPq3iCPj1KBMHh/Z1QclBtWD4 JO7MSJwml+8lD2QBHeM209GkMG/9KDa++liD9dJXUBIvA1MRiB53C4 X-Google-Smtp-Source: AK7set8uJrAxK7zzWtAFO1zi3yjBd8q2vMLLBoGWxyw3jYIZEOWdQuITvugaOxvBE7TuNh8UlzrCSQ== X-Received: by 2002:a05:6000:4a:b0:2c7:faf:af32 with SMTP id k10-20020a056000004a00b002c70fafaf32mr13809343wrx.14.1678384701278; Thu, 09 Mar 2023 09:58:21 -0800 (PST) Received: from [10.137.0.17] (xdsl.62.192.157.70.srvc.fr. [62.192.157.70]) by smtp.gmail.com with ESMTPSA id c9-20020adfe749000000b002bfd524255esm20784wrn.43.2023.03.09.09.58.20 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 09 Mar 2023 09:58:20 -0800 (PST) Message-ID: <2f680c4f-0944-5fd0-2e39-8cd95ccb89f5@enterprisedb.com> Date: Thu, 9 Mar 2023 18:58:20 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0 Subject: Re: Add LZ4 compression in pg_dump To: Justin Pryzby Cc: gkokolatos@pm.me, Michael Paquier , shiy.fnst@fujitsu.com, pgsql-hackers@lists.postgresql.org, Rachel Heaton References: <22cb80ed-ec87-54c7-fd5b-cdcf79766bb1@enterprisedb.com> <8421f53d-c9f7-c02e-3278-9f9522a8e8f3@enterprisedb.com> <20230224015115.GS1653@telsasoft.com> <20230225050214.GH1653@telsasoft.com> <20230225140553.GI1653@telsasoft.com> <20230227044910.GO1653@telsasoft.com> <09b37949-cfe5-29bb-cbb1-498ee5700b61@enterprisedb.com> Content-Language: en-US From: Tomas Vondra In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-CLOUD-SEC-AV-Info: enterprisedb,google_mail,monitor X-CLOUD-SEC-AV-Sent: true X-Gm-Spam: 0 X-Gm-Phishy: 0 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 3/9/23 17:15, Justin Pryzby wrote: > On Wed, Mar 01, 2023 at 05:39:54PM +0100, Tomas Vondra wrote: >> On 2/27/23 05:49, Justin Pryzby wrote: >>> On Sat, Feb 25, 2023 at 08:05:53AM -0600, Justin Pryzby wrote: >>>> On Fri, Feb 24, 2023 at 11:02:14PM -0600, Justin Pryzby wrote: >>>>> I have some fixes (attached) and questions while polishing the patch for >>>>> zstd compression. The fixes are small and could be integrated with the >>>>> patch for zstd, but could be applied independently. >>>> >>>> One more - WriteDataToArchiveGzip() says: >>> >>> One more again. >>> >>> The LZ4 path is using non-streaming mode, which compresses each block >>> without persistent state, giving poor compression for -Fc compared with >>> -Fp. If the data is highly compressible, the difference can be orders >>> of magnitude. >>> >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -Z lz4 -Fp |wc -c >>> 12351763 >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -Z lz4 -Fc |wc -c >>> 21890708 >>> >>> That's not true for gzip: >>> >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Z gzip -Fc |wc -c >>> 2118869 >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Z gzip -Fp |wc -c >>> 2115832 >>> >>> The function ought to at least use streaming mode, so each block/row >>> isn't compressioned in isolation. 003 is a simple patch to use >>> streaming mode, which improves the -Fc case: >>> >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -Z lz4 -Fc |wc -c >>> 15178283 >>> >>> However, that still flushes the compression buffer, writing a block >>> header, for every row. With a single-column table, pg_dump -Fc -Z lz4 >>> still outputs ~10% *more* data than with no compression at all. And >>> that's for compressible data. >>> >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Fc -Z lz4 |wc -c >>> 12890296 >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Fc -Z none |wc -c >>> 11890296 >>> >>> I think this should use the LZ4F API with frames, which are buffered to >>> avoid outputting a header for every single row. The LZ4F format isn't >>> compatible with the LZ4 format, so (unlike changing to the streaming >>> API) that's not something we can change in a bugfix release. I consider >>> this an Opened Item. >>> >>> With the LZ4F API in 004, -Fp and -Fc are essentially the same size >>> (like gzip). (Oh, and the output is three times smaller, too.) >>> >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Z lz4 -Fp |wc -c >>> 4155448 >>> $ ./src/bin/pg_dump/pg_dump -h /tmp postgres -t t1 -Z lz4 -Fc |wc -c >>> 4156548 >> >> Thanks. Those are definitely interesting improvements/optimizations! >> >> I suggest we track them as a separate patch series - please add them to >> the CF app (I guess you'll have to add them to 2023-07 at this point, >> but we can get them in, I think). > > Thanks for looking. I'm not sure if I'm the best person to write/submit > the patch to implement that for LZ4. Georgios, would you want to take > on this change ? > > I think that needs to be changed for v16, since 1) LZ4F works so much > better like this, and 2) we can't change it later without breaking > compatibility of the dumpfiles by changing the header with another name > other than "lz4". Also, I imagine we'd want to continue supporting the > ability to *restore* a dumpfile using the old(current) format, which > would be untestable code unless we also preserved the ability to write > it somehow (like -Z lz4-old). > I'm a bit confused about the lz4 vs. lz4f stuff, TBH. If we switch to lz4f, doesn't that mean it (e.g. restore) won't work on systems that only have older lz4 version? What would/should happen if we take backup compressed with lz4f, an then try restoring it on an older system where lz4 does not support lz4f? Maybe if lz4f format is incompatible with regular lz4, we should treat it as a separate compression method 'lz4f'? I'm mostly afk until the end of the week, but I tried searching for lz4f info - the results are not particularly enlightening, unfortunately. AFAICS this only applies to lz4f stuff. Or would the streaming mode be a breaking change too? > One issue is that LZ4F_createCompressionContext() and > LZ4F_compressBegin() ought to be called in InitCompressorLZ4(). It > seems like it might *need* to be called there to avoid exactly the kind > of issue that I reported with empty LOs with gzip. But > InitCompressorLZ4() isn't currently passed the ArchiveHandle, so can't > write the header. And LZ4CompressorState has a simple char *buf, and > not an more elaborate data structure like zlib. You could work around > that by keeping storing the "len" of the existing buffer, and flushing > it in EndCompressorLZ4(), but that adds needless complexity to the Write > and End functions. Maybe the Init function should be passed the AH. > Not sure, but looking at GzipCompressorState I see the only extra thing it has (compared to LZ4CompressorState) is "z_streamp". I can't experiment with this until the end of this week, so perhaps that's not workable, but wouldn't it be better to add a similar field into LZ4CompressorState? Passing AH to the init function seems like a violation of abstraction. regards -- Tomas Vondra EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company