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 1s6Zgr-000Rh6-HM for pgsql-hackers@arkaria.postgresql.org; Mon, 13 May 2024 17:42:23 +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 1s6Zgr-00322X-Gr for pgsql-hackers@arkaria.postgresql.org; Mon, 13 May 2024 17:42:21 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1s6Zgr-003225-0C for pgsql-hackers@lists.postgresql.org; Mon, 13 May 2024 17:42:21 +0000 Received: from mail-ej1-x62b.google.com ([2a00:1450:4864:20::62b]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1s6Zgm-0002rv-W0 for pgsql-hackers@lists.postgresql.org; Mon, 13 May 2024 17:42:20 +0000 Received: by mail-ej1-x62b.google.com with SMTP id a640c23a62f3a-a59a352bbd9so766188866b.1 for ; Mon, 13 May 2024 10:42:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cybertec-at.20230601.gappssmtp.com; s=20230601; t=1715622136; x=1716226936; darn=lists.postgresql.org; h=message-id:date:content-transfer-encoding:content-id:mime-version :comments:references:in-reply-to:subject:cc:to:from:from:to:cc :subject:date:message-id:reply-to; bh=cMFYXfdlDxvXCorJBw88L9tIy6SxYZV8sUrpde4PJo4=; b=jj2CepWuUaPJ8Ht6WCbdcjWWIzKsruJq1JHJrl0Pv07gVUYrG7+daI82tiiFSSGHcX n7rzqna7137lvlBK1WaR0oka2WP8Ei4u6FqcJGmlU2C3/wjmONtrh0mfYlh8aQLrOdrg k/0dW7CsNQg7jeofqt+dRkKyR5GMt3o58jbqiNf7a0rzAvvkn0vyhWa3rVLF/xSNqP8W 7tOgbTraR6LSQR4H9q9bTsf4Em5s6rfzTfeP3deCoEkbNIhVv0BdthRd7/DMgF0GgmhM p17sl7Uz2u4/OJnxKJHukJbieTYDKMlWwC4IDAQ7TRl/J4aN8H4BzIHHkrpCfqBA/BWY 4DRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715622136; x=1716226936; h=message-id:date:content-transfer-encoding:content-id:mime-version :comments:references:in-reply-to:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=cMFYXfdlDxvXCorJBw88L9tIy6SxYZV8sUrpde4PJo4=; b=sTyezjPcU9Mn7rcyjf7KQRkjH3HEwwvHnwv3WY0FHMcFfpu9rAHWhsONLYorVZ9mJX bpnWLggKYMWBrPRcqlJ5IyY2ctmLimfhFPpWi53Grmqwk0JYcGFp9L7s0mywEet5xqPA Tgz3Lzl2cZTmvbUHoxC3NCXV5pM6eaU1dPE1otzZkP2F5Q8mg2J0er6oUntajcxM935o ZUw0wY78w0hvHYbEof6OvHBrK+HncTFC0fR7Ilrb+HbXYrXKLS2Ivg8i2ofs/fs9/v27 UCM6aQFk3PFNW3hs/JLJjSpXO7DKvCVjH4jwe6/CPQtbojYgvxTw44y7/pzXoX7vwRNm bblg== X-Gm-Message-State: AOJu0YybXID8hSKKNy45Pth4PDP4Lm0wpAiOpm2RgkETMBHqwQ9AtWnQ b6RF9IzN/SsgS4V5Y3/ApXduwrJUgbpOUe+ilDU3UH6Arp6UtIx34GFxGp0W1vg= X-Google-Smtp-Source: AGHT+IFW6riyX6iD8gcN1yGSeluJd4zkrt4DpWIhmJabUWNUq5rDxoLKT+RI4XN7mPrDyVPi1d2McQ== X-Received: by 2002:a17:906:bc50:b0:a59:cb28:a8ae with SMTP id a640c23a62f3a-a5a1123b477mr1118064166b.0.1715622136196; Mon, 13 May 2024 10:42:16 -0700 (PDT) Received: from antos (109-81-174-135.rct.o2.cz. [109.81.174.135]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a5a5386d44dsm357789866b.91.2024.05.13.10.42.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 May 2024 10:42:15 -0700 (PDT) From: Antonin Houska To: Andy Fan Cc: PostgreSQL Hackers , David Rowley , Tom Lane , Ashutosh Bapat , jian he Subject: Re: UniqueKey v2 In-reply-to: <3739.1715594150@antos> References: <7mlamswjp81p.fsf@e18c07352.et15sqa> <871qczm9oc.fsf@163.com> <7971.1713526758@antos> <875xvrnzga.fsf@163.com> <3739.1715594150@antos> Comments: In-reply-to Antonin Houska message dated "Mon, 13 May 2024 11:55:50 +0200." X-Mailer: MH-E 8.6+git; nmh 1.8; GNU Emacs 28.2.50 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <4985.1715622135.1@antos> Content-Transfer-Encoding: quoted-printable Date: Mon, 13 May 2024 19:42:15 +0200 Message-ID: <4986.1715622135@antos> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Antonin Houska wrote: > Andy Fan wrote: > > > > > > * Combining the UKs > > > > > > IMO this is the most problematic part of the patch. You call > > > populate_joinrel_uniquekeys() for the same join multiple times, > > = > > Why do you think so? The below code is called in "make_join_rel" > = > Consider join of tables "a", "b" and "c". My understanding is that > make_join_rel() is called once with rel1=3D{a} and rel2=3D{b join c}, th= en with > rel1=3D{a join b} and rel2=3D{c}, etc. I wanted to say that each call sh= ould > produce the same set of unique keys. > = > I need to check this part more in detail. I think I understand now. By calling populate_joinrel_uniquekeys() for var= ious orderings, you can find out that various input relation unique keys can represent the whole join. For example, if the ordering is A JOIN (B JOIN C) you can prove that the unique keys of A can be used for the whole join, wh= ile for the ordering B JOIN (A JOIN C) you can prove the same for the unique keys of B, and so on. > > Is your original question is about populate_joinrel_uniquekey_for_rel > > rather than populate_joinrel_uniquekeys? We have the below codes: > > = > > outeruk_still_valid =3D populate_joinrel_uniquekey_for_rel(root, join= rel, outerrel, > > innerrel, restrictlist); > > inneruk_still_valid =3D populate_joinrel_uniquekey_for_rel(root, join= rel, innerrel, > > outerrel, restrictlist); > > = > > This is mainly because of the following theory. Quoted from > > README.uniquekey. Let's called this as "rule 1". > > = > > """ > > How to maintain the uniquekey? > > ------------------------------- > > .. From the join relation, it is maintained with two rules: > > = > > - the uniquekey in one side is still unique if it can't be duplicated > > after the join. for example: > > = > > SELECT t1.pk FROM t1 JOIN t2 ON t1.a =3D t2.pk; > > UniqueKey on t1: t1.pk > > UniqueKey on t1 Join t2: t1.pk > > """ > > = > > AND the blow codes: > > = > > = > > if (outeruk_still_valid || inneruk_still_valid) > > = > > /* > > * the uniquekey on outers or inners have been added into joinrel so > > * the combined uniuqekey from both sides is not needed. > > */ > > return; > > = > > = > > We don't create the component uniquekey if any one side of the boths > > sides is unique already. For example: > > = > > "(t1.id) in joinrel(t1, t2) is unique" OR "(t2.id) in joinrel is > > unique", there is no need to create component UniqueKey (t1.id, t2.id)= ; = > = > ok, I need to check more in detail how this part works. This optimization makes sense to me. > > > > > > Of course one problem is that the number of combinations can grow > > > exponentially as new relations are joined. > > = > > Yes, that's why "rule 1" needed and "How to reduce the overhead" in > > UniqueKey.README is introduced. = I think there should yet be some guarantee that the number of unique keys = does not grow exponentially. Perhaps a constant that allows a relation (base or join) to have at most N unique keys. (I imagine N to be rather small, e.g.= 3 or 4.) And when picking the "best N keys", one criterion could be the numb= er of expressions in the key (the shorter key the better). > > > > > > 2) Check if the join relation is single-row > > > > > > I in order to get rid of the dependency on 'restrictlist', I think= you can > > > use ECs. Consider a query from your regression tests: > > > > > > CREATE TABLE uk_t (id int primary key, a int not null, b int not nul= l, c int, d int, e int); > > > > > > SELECT distinct t1.d FROM uk_t t1 JOIN uk_t t2 ON t1.e =3D t2.id and= t1.id =3D 1; > > > > > > The idea here seems to be that no more than one row of t1 matches = the query > > > clauses. Therefore, if t2(id) is unique, the clause t1.e=3Dt2.id e= nsures that > > > no more than one row of t2 matches the query (because t1 cannot pr= ovide the > > > clause with more than one input value of 'e'). And therefore, the = join also > > > produces at most one row. > > = > > You are correct and IMO my current code are able to tell it is a singl= e > > row as well. > > = > > 1. Since t1.id =3D 1, so t1 is single row, so t1.d is unqiuekey as a > > consequence. > > 2. Given t2.id is unique, t1.e =3D t2.id so t1's unqiuekey can be kept > > after the join because of rule 1 on joinrel. and t1 is singlerow, so t= he > > joinrel is singlerow as well. ok, I think I understand now. -- = Antonin Houska Web: https://www.cybertec-postgresql.com