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.96) (envelope-from ) id 1vpMFC-006OEt-0C for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Feb 2026 08:03:42 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vpMFB-009l9I-0S for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Feb 2026 08:03:40 +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.96) (envelope-from ) id 1vpMFA-009l9A-2b for pgsql-hackers@lists.postgresql.org; Mon, 09 Feb 2026 08:03:40 +0000 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vpMF8-00000001mXp-1CDe for pgsql-hackers@postgresql.org; Mon, 09 Feb 2026 08:03:40 +0000 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-35640ad94d3so517750a91.1 for ; Mon, 09 Feb 2026 00:03:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1770624215; cv=none; d=google.com; s=arc-20240605; b=QM+1WpT/kzts/iCkrl+Y6XryCwvoJ7Gp76On6Wj8sn7KfMYMk3vR9KZ91ZxKd3M0Oz uxGodq71bsJuX++sgawql9IaqXndEeeBXZNAAKikML2F84jO+wkBCkPIUKEPvuUSbhmH 94GuML6tLtcvtIcj7CfOUD95jevmMrqWwIPVk9rfyoT9bdm6HPklx8MzKVAZPanTlHTD VzmgwTkN/KbPVs0YrAHLjNlEAa6m5NPllNCdpWZRWAa9sHdEyM/MmzJS9cEUkLkeHvbe FIK/g3LJpWE6Ec7qYnK2nXZ9Gk6Op3zTjvqj6pZmHTWLq976JZNULrxxdxPb2UuCEQLz lOvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version:dkim-signature; bh=X0IVgKSXUWnkmLjeTjdU7jlRl6C7fN5B2rjbkZzhvcc=; fh=e6yVbx5VwJNf4wEocyZRCb30Vu9SMHZGgMClG8w8ods=; b=ekiaB2gO6/SiEEnClW6IMQFbXDZB2z8jpQR6VxQR4Z2WHBVD4G627Dwl3SLDhdn2bf HoTmEE692aO37wrk6IzoyFkcxkMKF0tuyMqlJusbopMVmJLMeZAd5EwkanAfiXO84O8z 3V7R7qmt8RuEuveQ0tu0Gn1CDFYv4ROkkPw1xzFmyW5sIsdvXdijc679upBOf7uOkJDg n0400Ogn2Vk96ogUrXSf8LJeDKg8kEvo+/ZgN4M3o4HDW5ISvVb3X2pKt1kslfSWSlrF Hif13pxVk45CscFviQ9QNRRg5aiqf989AYrK/MKY6iTUxhZ34iMsroLrTkqxxujWWxD8 x2pw==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770624215; x=1771229015; darn=postgresql.org; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=X0IVgKSXUWnkmLjeTjdU7jlRl6C7fN5B2rjbkZzhvcc=; b=Qr6ZZViEzE36RUBumwrnecozcHYySbgY5twrdsrtq6g1qbghs79kLxl8uf0JL43fet gb2rXTLvPrvbgBr8lbXK21hAfhoxVintm9ZYsBmepRUftxNqdvJNVSl4F2rWmvK4koS+ AUZdUgGlu4mblM0928SBgKuWwFUH/BcJ2LsCbai+pRm4C8JbDKJE8X5a+2Y/kcXKHv6y 1W6uJvBbvBUfqZnWLqkycAQoUr7E/shZM6I4226X5U8G3zJBHSrigTAUfQctvuNqvImN w/7iYf+f6eHl9SqPW56pvDzdNag7uX1M3Nyq3bp9z38EeNh7SHNXREe4747deWwfjSDA gS8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770624215; x=1771229015; h=cc:to:subject:message-id:date:from:reply-to:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=X0IVgKSXUWnkmLjeTjdU7jlRl6C7fN5B2rjbkZzhvcc=; b=xQR6OlycmH52ITgrnP6XgZDe4MKNNDD2fjWij5DNBca4Q8o4tpktTeQpM7obd8Ykei Pe040eUGp066x/POWj3FLYQqpfNhlIOryuiv7Ibtht25v5vNKz/X9Ml2u8ham0Hw0NbJ 97Fip4IsGLFn6fcm5xOzky57DgowFzTIe9dx1+P5slDUqMRUbdCPaAtcFxHtJ96pZdf/ H4ZXH0ooRbFG3SMVdw37ck+U6aTAQ1wqQnQ7zdjv+DCfgMb9kAxkdpHV+H0JDosQCOaq XrwwXPQfzInhM5kKUdJyIomCfLC89oH/LuZdSKxyyvAQEnSSJ4QLb33zwddW03XsDwfX KNFA== X-Forwarded-Encrypted: i=1; AJvYcCVSEqH6o8fXyNsJE0kTGs0uTmT6DnAPmlyx1oYUPzOwqZtJauB6l0GEDOk/QcXcsp7laIGtxQe2frBQqTep@postgresql.org X-Gm-Message-State: AOJu0Yy8u6GI3Eb096eXqJaBPIJZR6/8q9IalqpF29uYIuk+50Het3YT FMKUQ40OtQ1lYKDCErFIDFwziPmvEa/kc0FvatfgdoV/fMI5n70f4/BovVtGjTGDET02ZYTImdl /lcy4COjC3+v5v6h+f4IPJNA18PXBy3I= X-Gm-Gg: AZuq6aKoibBziGT2mPTdnFDMS6LnM1GoQH3um0COEn8ItzUV1anEVO0CY7X4XWfWTUY kUMFujIYMp/y6Ste279yaDa0KwC5ieQ3Hx6ed4nKNcg20dM/uhaneLtS/raF5o97GCff1fa8PpJ 8QakMIkDKPD0D34csJvEcLlBRN8gSHXWOJ3R4r6cu84bW4c62wxLcWbpLXCs6OybR3jpgOWu80C OiNIE0u2PUIuDEcaL04LRgZgDBME+l4/7s+EXYMXFhCucnsYZOg5UcivYLqwJseoZDAqrqSGE12 ORYMdV+SAixr18DoeOuG6AmOcd8= X-Received: by 2002:a17:90b:258b:b0:354:a284:3ff9 with SMTP id 98e67ed59e1d1-354b3e4478amr9306180a91.26.1770624215395; Mon, 09 Feb 2026 00:03:35 -0800 (PST) MIME-Version: 1.0 References: <20260207.133143.1951390390459539453.ishii@postgresql.org> <20260209.160520.873483599710391856.ishii@postgresql.org> In-Reply-To: <20260209.160520.873483599710391856.ishii@postgresql.org> Reply-To: assam258@gmail.com From: Henson Choi Date: Mon, 9 Feb 2026 17:03:23 +0900 X-Gm-Features: AZwV_QjnFK8aa4TpKmyGMg3kJVx_noN8Ax6-YnaD_FHbR53LkZydvmwLVerKXRw Message-ID: Subject: Re: Row pattern recognition To: Tatsuo Ishii , jacob.champion@enterprisedb.com Cc: david.g.johnston@gmail.com, vik@postgresfriends.org, er@xs4all.nl, peter@eisentraut.org, pgsql-hackers@postgresql.org Content-Type: multipart/alternative; boundary="00000000000063b1e1064a5f93ae" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000063b1e1064a5f93ae Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Tatsuo, Thank you for the thorough testing and performance profiling! BTW, I have tested RPR with large partition/reduced frame (up to 100k > rows). Following query took over 3 minutes on my laptop. > The profiling results are very insightful and help us understand where the time is spent in extreme cases. > I don't try to say we should enhance nfa modules in the case when > there is a large reduced frame, because I don't think this is a > realistic use case and I doubt it's worth to fight against unrealistic > scenario. > I agree with your assessment. Let me clarify: The pattern itself (START UP+) is realistic - it's a common pattern for detecting upward trends. However, 100k+ consecutive matches without interruption is not realistic. Your UP{,3} example (94ms for 100k partition= ) demonstrates that the current implementation performs very well for realistic use cases. > I think this is more realistic use case than former. If I were > correct, we don't need to work on current nfa code to squeeze better > performance for unrealistic 100k reduced frame case. I maybe wrong > and I would love to hear from others especially, Henson, Vik, Jacob. I agree that we should prioritize realistic use cases. That said, there are potential optimizations that could help: 1. Anchored pattern absorption (see my earlier message: https://www.postgresql.org/message-id/CAAAe_zAEg7sVM%3DWDwXMyE-odGmQyXSVi5Z= zWgye6SupSjdMKpg%40mail.gmail.com ) 2. Alt-pruning: In patterns like "A* | B*", once the higher-priority A branch has a confirmed match, the B branch can be pruned immediately. Even if B could continue extending to a longer match, it can never be selected due to lexical order semantics=E2=80=94A will always win. This proactive prunin= g respects SQL standard semantics while reducing unnecessary state expansion. However, given the complexity of NFA internals, I believe we should take a step-by-step approach: 1. First, stabilize the current RPR patch and prepare it for review 2. Then, consider optimizations as separate follow-up patches 3. Each optimization should be well-tested and reviewed independently This approach reduces risk and makes review more manageable. The fact that the current implementation handles even unrealistic 100k-row cases without crashing (just slowly) shows it's already robust. What do you think about this phased approach? Best regards, Henson P.S. I discovered a crash bug that was introduced in the latest patch refactoring. The issue occurs with nested alternation patterns like (A+ | (A | B)+)*, where infinite recursion happens in nfa_advance_alt when the inner BEGIN(+)'s skip jump is followed as an ALT branch pointer. I will include the fix in the next patch update. --00000000000063b1e1064a5f93ae Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Tatsuo,

Thank you for the thoro= ugh testing and performance profiling!

BTW, I have tested RPR with large partition/reduced frame (up to 100k
rows). Following query took over 3 minutes on my laptop.

The profiling results are very insightful and help us understa= nd where
the time is spent in extreme cases.
=C2=A0
I don't try to say we should enhance nfa modules in the case when
there is a large reduced frame, because I don't think this is a
realistic use case and I doubt it's worth to fight against unrealistic<= br> scenario.

I agree with your assessment. Let = me clarify:

The pattern itself (START UP+) is realistic - it's a= common pattern for
detecting upward trends. However, 100k+ consecutive = matches without
interruption is not realistic. Your UP{,3} example (94ms= for 100k partition)
demonstrates that the current implementation perfor= ms very well for realistic
use cases.
=C2=A0
I think this is more realistic use case than former. If I were
correct, we don't need to work on current nfa code to squeeze better performance for unrealistic 100k reduced frame case. I maybe wrong
and I would love to hear from others especially, Henson, Vik, Jacob.

I agree that we should prioritize realistic use cases.= That said, there are
potential optimizations that could help:

1.= Anchored pattern absorption (see my earlier message:
=C2=A0 =C2=A0https://www.postgresql.org/message= -id/CAAAe_zAEg7sVM%3DWDwXMyE-odGmQyXSVi5ZzWgye6SupSjdMKpg%40mail.gmail.com<= /a>)

2. Alt-pruning: In patterns like "A* | B*", once the = higher-priority A branch
=C2=A0 =C2=A0has a confirmed match, the B branc= h can be pruned immediately. Even if B
=C2=A0 =C2=A0could continue exten= ding to a longer match, it can never be selected due to
=C2=A0 =C2=A0lex= ical order semantics=E2=80=94A will always win. This proactive pruning resp= ects
=C2=A0 =C2=A0SQL standard semantics while reducing unnecessary stat= e expansion.

However, given the complexity of NFA internals, I belie= ve we should take a
step-by-step approach:

1. First, stabilize th= e current RPR patch and prepare it for review
2. Then, consider optimiza= tions as separate follow-up patches
3. Each optimization should be well-= tested and reviewed independently

This approach reduces risk and mak= es review more manageable. The fact that
the current implementation hand= les even unrealistic 100k-row cases without
crashing (just slowly) shows= it's already robust.

What do you think about this phased approa= ch?

Best regards,
Henson

P.S. I discovered a crash bug tha= t was introduced in the latest patch
refactoring. The issue occurs with = nested alternation patterns like
(A+ | (A | B)+)*, where infinite recurs= ion happens in nfa_advance_alt when
the inner BEGIN(+)'s skip jump i= s followed as an ALT branch pointer. I will
include the fix in the = next patch update.=C2=A0
--00000000000063b1e1064a5f93ae--