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 1nwVu8-00070y-14 for pgsql-hackers@arkaria.postgresql.org; Wed, 01 Jun 2022 21:29:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nwVu6-0004n5-KM for pgsql-hackers@arkaria.postgresql.org; Wed, 01 Jun 2022 21:29:22 +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 1nwVu6-0004mo-9E for pgsql-hackers@lists.postgresql.org; Wed, 01 Jun 2022 21:29:22 +0000 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1nwVu3-0005yC-UN for pgsql-hackers@lists.postgresql.org; Wed, 01 Jun 2022 21:29:21 +0000 Received: by mail-pf1-x42f.google.com with SMTP id w21so3117805pfc.0 for ; Wed, 01 Jun 2022 14:29:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=timescale.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=9eTF0zdLJVuCS76Ydu6cIhFRKaHQTXrVpsYvVSf4yVw=; b=Ep8qPC2m0fz5nyUJcKYHqQq2ZFvyWHTVBXXdOt+DWKyMU+GkAhv7nxESipPVVCadyY //kHmbTth4PJg9ziuMlJfgP+Tu93b60zAy0VW1oxigzowtx4RShCKu9msgm1n1kFa7qj 6DyRmKmUAHBMR45eBAR+mQqTp9RUWnZpIipYoELv94WSgvWrQ9ZSUeogii4t8SsEfaii TDQM4x59yVv4max3IwIDES6A5XF97lIKOA5UOlPBBwPPF1otZVay348sleepwD1Kf8Oz fkqY+oExie652pVFxIYO3qmo9amTZF/TWzJMGg2INKeXJt26VG8GeqNiUqYyUJoERT/+ cNSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=9eTF0zdLJVuCS76Ydu6cIhFRKaHQTXrVpsYvVSf4yVw=; b=ouxi8/zFEv3pGCPgkt2Efu31t9QdwQTnLX1aFZfCb/8LFG2VD0Q2GIHHfXvrN/T6Ou kyI55q1ppH8imM2RT+ZSgwITc5CF3Io/XjYCizbD1r/5eWF0ku6VVgzB4AIB7OWpY2X6 ljfa9i8THtZxH2Tz7j9EQYHOykp0tROu6Kn9ON7iUtbCELLKGOIUwWCM5qmOHkXsQtxe CiHoIxcKMPESGWRSpy0jjA8OdjYSpnYlmYSmGgwn70QlJdSsNQKmpodYpc+ZH451Dllr IBo2dnHUh5gq+gbjag5dEPfQba6i9ffw8D0GRr/V1CpEsEjYhhFxGxXrdKVU9cB/G8Hc /z+A== X-Gm-Message-State: AOAM532fe7QOK+MwT5Xv4CCb63IgVF8gfxiFYEIFVIfsPEe1gmCm13IK tJcm+epsy7J4sauMK9yjoaqeWvmOAbrWLmorGGfKgQ== X-Google-Smtp-Source: ABdhPJyEFX+uPHkBj7fG1Hr5Khsw0E6rR/8wHIA55XMqfygMz2JR2FfU2+gwHbAArHfXmgS64mgrq34ZekKekaJvf1g= X-Received: by 2002:a62:7cca:0:b0:4fd:e594:fac0 with SMTP id x193-20020a627cca000000b004fde594fac0mr1494553pfc.79.1654118958000; Wed, 01 Jun 2022 14:29:18 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Jacob Champion Date: Wed, 1 Jun 2022 14:29:06 -0700 Message-ID: Subject: Re: [PATCH] Compression dictionaries for JSONB To: Aleksander Alekseev Cc: PostgreSQL Hackers , Alvaro Herrera , Matthias van de Meent 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 Wed, Jun 1, 2022 at 1:44 PM Aleksander Alekseev wrote: > This is a follow-up thread to `RFC: compression dictionaries for JSONB` [= 1]. I would like to share my current progress in order to get early feedbac= k. The patch is currently in a draft state but implements the basic functio= nality. I did my best to account for all the great feedback I previously go= t from Alvaro and Matthias. I'm coming up to speed with this set of threads -- the following is not a complete review by any means, and please let me know if I've missed some of the history. > SELECT * FROM pg_dict; > oid | dicttypid | dictentry > -------+-----------+----------- > 39476 | 39475 | aaa > 39477 | 39475 | bbb > (2 rows) I saw there was some previous discussion about dictionary size. It looks like this approach would put all dictionaries into a shared OID pool. Since I don't know what a "standard" use case is, is there any risk of OID exhaustion for larger deployments with many dictionaries? Or is 2**32 so comparatively large that it's not really a serious concern? > When `mydict` sees 'aaa' in the document, it replaces it with the corresp= onding code, in this case - 39476. For more details regarding the compressi= on algorithm and choosen compromises please see the comments in the patch. I see the algorithm description, but I'm curious to know whether it's based on some other existing compression scheme, for the sake of comparison. It seems like it shares similarities with the Snappy scheme? Could you talk more about what the expected ratios and runtime characteristics are? Best I can see is that compression runtime is something like O(n * e * log d) where n is the length of the input, e is the maximum length of a dictionary entry, and d is the number of entries in the dictionary. Since e and d are constant for a given static dictionary, how well the dictionary is constructed is presumably important. > In pg_type `mydict` has typtype =3D TYPTYPE_DICT. It works the same way a= s TYPTYPE_BASE with only difference: corresponding `_in` (pg_type.typ= input) and `_` (pg_cast.castfunc) procedures receive th= e dictionary Oid as a `typmod` argument. This way the procedures can distin= guish `mydict1` from `mydict2` and use the proper compression dictionary. > > The approach with alternative `typmod` role is arguably a bit hacky, but = it was the less invasive way to implement the feature I've found. I'm open = to alternative suggestions. Haven't looked at this closely enough to develop an opinion yet. > Current limitations (todo): > - ALTER TYPE is not implemented That reminds me. How do people expect to generate a "good" dictionary in practice? Would they somehow get the JSONB representations out of Postgres and run a training program over the blobs? I see some reference to training functions in the prior threads but don't see any breadcrumbs in the code. > - Alternative compression algorithms. Note that this will not require any= further changes in the catalog, only the values we write to pg_type and pg= _cast will differ. Could you expand on this? I.e. why would alternative algorithms not need catalog changes? It seems like the only schemes that could be used with pg_catalog.pg_dict are those that expect to map a byte string to a number. Is that general enough to cover other standard compression algorithms? > Open questions: > - Dictionary entries are currently stored as NameData, the same type that= is used for enums. Are we OK with the accompanying limitations? Any altern= ative suggestions? It does feel a little weird to have a hard limit on the entry length, since that also limits the compression ratio. But it also limits the compression runtime, so maybe it's a worthwhile tradeoff. It also seems strange to use a dictionary of C strings to compress binary data; wouldn't we want to be able to compress zero bytes too? Hope this helps, --Jacob