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 1rLuog-001Mic-L6 for pgsql-hackers@arkaria.postgresql.org; Sat, 06 Jan 2024 00:45:35 +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 1rLuof-005l2G-7C for pgsql-hackers@arkaria.postgresql.org; Sat, 06 Jan 2024 00:45:33 +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 1rLuoe-005l20-TM for pgsql-hackers@lists.postgresql.org; Sat, 06 Jan 2024 00:45:32 +0000 Received: from mail-ua1-x932.google.com ([2607:f8b0:4864:20::932]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rLuoc-0004oq-0y for pgsql-hackers@postgresql.org; Sat, 06 Jan 2024 00:45:31 +0000 Received: by mail-ua1-x932.google.com with SMTP id a1e0cc1a2514c-7cdf4b99e7eso44311241.0 for ; Fri, 05 Jan 2024 16:45:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1704501928; x=1705106728; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=Ht/Sz5xsGRtkmx679LcTYG+ktsV1PqSQciZLqm46vPk=; b=AVgQJOAyHfZT0aKlGsrfOtgH7YfFtJGwdC0PpqNrKlQTvRXj7Oi9WANTb+0vx6E60+ U6xuKUVFu0sJA47JuudQQXERv10fwyKKB43Om6xlGs0/zLezsTAx5Ex302t0MROTOnGe TxaWRQMmPUqXYoGkY9Axvd2cS74vnvYT40IVLLrlV5Z9RtlE4s9QQ5a+7LYlupJMDoz3 D9ipBhT4p38t1sdwhYyZjgRrDXb3/4R3Ty8eZjz3YDJ5XWwB8PcVeK9/7QuUIif/+njl 9zozSkRR4sNyoBL1qw0t1PMtvKId906F4svndoHykCWpUqYVjhX9MZVQvspKC/noe19p JVbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704501928; x=1705106728; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Ht/Sz5xsGRtkmx679LcTYG+ktsV1PqSQciZLqm46vPk=; b=a+AfoUihy6F5AdJUORT/xZHx49vIGqu8iDZOSalFz9Ca5nx5Yb34D8lGvSILLAqw/m GXAxA+phdWZksXhwikQpPfpWZeOcdj2Nu0y5QWCiZE3otwqNax2tH9XNQTcyfLo7TSCs +fTzzwn8a8efik8Io1/4gBghwPI36qrWTJUFgPP+plZSlhWpkb5oodX58KfQvuMyu3kr m3GEkoCrdxLIWymoonej1dnfo9T3AYv+XF1QFjPrAaUatxNNSb8K50cftYy3z6XEA+tt r8cL6rEIQjNcwk5wOkrNIeSKzidquIKRdsEU64b1gnKl28Pzp4y9UrlO88mPWUB9Ybx8 AyAg== X-Gm-Message-State: AOJu0YyHLqHX6n/e4T8S12Ln7gPUIzyk03eapYMvftp5c4aW94zRTmOI Dr8X7qKQkpSk1v6y5xks8pQt28USg0/6wrIHRNw= X-Google-Smtp-Source: AGHT+IFLtOKGQJWKu9TYYeph68wMqk5OmoWGugkvVYOYmCU8rcUjQCC8sbUTeAH8YQxw5AB5Acg4iOiWN9kfhjVwoIM= X-Received: by 2002:a05:6102:2907:b0:467:6446:8413 with SMTP id cz7-20020a056102290700b0046764468413mr205443vsb.57.1704501927826; Fri, 05 Jan 2024 16:45:27 -0800 (PST) MIME-Version: 1.0 References: <202312071051.cpxujwos4tlj@alvherre.pgsql> <20231208173014.2qycwc6kjqf6zlck@awork3.anarazel.de> In-Reply-To: From: jian he Date: Sat, 6 Jan 2024 08:44:00 +0800 Message-ID: Subject: Re: remaining sql/json patches To: Amit Langote Cc: Andres Freund , Alvaro Herrera , Erik Rijkers , Andrew Dunstan , PostgreSQL-development Content-Type: text/plain; charset="UTF-8" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk some tests after applying V33 and my small changes. setup: create table test_scalar1(js jsonb); insert into test_scalar1 select jsonb '{"a":"[12,13]"}' FROM generate_series(1,1e5) g; create table test_scalar2(js jsonb); insert into test_scalar2 select jsonb '{"a":12}' FROM generate_series(1,1e5) g; create table test_array1(js jsonb); insert into test_array1 select jsonb '{"a":[1,2,3,4,5]}' FROM generate_series(1,1e5) g; create table test_array2(js jsonb); insert into test_array2 select jsonb '{"a": "{1,2,3,4,5}"}' FROM generate_series(1,1e5) g; tests: ----------------------------------------return a scalar int4range explain(costs off,analyze) SELECT item FROM test_scalar1, JSON_TABLE(js, '$.a' COLUMNS (item int4range PATH '$' omit quotes)) \watch count=5 237.753 ms explain(costs off,analyze) select json_query(js, '$.a' returning int4range omit quotes) from test_scalar1 \watch count=5 462.379 ms explain(costs off,analyze) select json_value(js,'$.a' returning int4range) from test_scalar1 \watch count=5 362.148 ms explain(costs off,analyze) select (js->>'a')::int4range from test_scalar1 \watch count=5 301.089 ms explain(costs off,analyze) select trim(both '"' from jsonb_path_query_first(js,'$.a')::text)::int4range from test_scalar1 \watch count=5 643.337 ms ----------------------------return a numeric array from jsonb array. explain(costs off,analyze) SELECT item FROM test_array1, JSON_TABLE(js, '$.a' COLUMNS (item numeric[] PATH '$')) \watch count=5 727.807 ms explain(costs off,analyze) SELECT json_query(js, '$.a' returning numeric[]) from test_array1 \watch count=5 2995.909 ms explain(costs off,analyze) SELECT replace(replace(js->>'a','[','{'),']','}')::numeric[] from test_array1 \watch count=5 2990.114 ms ----------------------------return a numeric array from jsonb string explain(costs off,analyze) SELECT item FROM test_array2, JSON_TABLE(js, '$.a' COLUMNS (item numeric[] PATH '$' omit quotes)) \watch count=5 237.863 ms explain(costs off,analyze) SELECT json_query(js,'$.a' returning numeric[] omit quotes) from test_array2 \watch count=5 893.888 ms explain(costs off,analyze) SELECT trim(both '"' from(jsonb_path_query(js,'$.a')::text))::numeric[] from test_array2 \watch count=5 1329.713 ms explain(costs off,analyze) SELECT (js->>'a')::numeric[] from test_array2 \watch count=5 740.645 ms explain(costs off,analyze) SELECT trim(both '"' from (json_query(js,'$.a' returning text)))::numeric[] from test_array2 \watch count=5 1085.230 ms ----------------------------return a scalar numeric explain(costs off,analyze) SELECT item FROM test_scalar2, JSON_TABLE(js, '$.a' COLUMNS (item numeric PATH '$' omit quotes)) \watch count=5 238.036 ms explain(costs off,analyze) select json_query(js,'$.a' returning numeric) from test_scalar2 \watch count=5 300.862 ms explain(costs off,analyze) select json_value(js,'$.a' returning numeric) from test_scalar2 \watch count=5 160.035 ms explain(costs off,analyze) select jsonb_path_query_first(js,'$.a')::numeric from test_scalar2 \watch count=5 294.666 ms explain(costs off,analyze) select jsonb_path_query(js,'$.a')::numeric from test_scalar2 \watch count=5 547.130 ms explain(costs off,analyze) select (js->>'a')::numeric from test_scalar2 \watch count=5 243.652 ms explain(costs off,analyze) select (js->>'a')::numeric, (js->>'a')::numeric from test_scalar2 \watch count=5 403.183 ms explain(costs off,analyze) select json_value(js,'$.a' returning numeric), json_value(js,'$.a' returning numeric) from test_scalar2 \watch count=5 246.405 ms explain(costs off,analyze) select json_query(js,'$.a' returning numeric), json_query(js,'$.a' returning numeric) from test_scalar2 \watch count=5 520.754 ms explain(costs off,analyze) SELECT item, item1 FROM test_scalar2, JSON_TABLE(js, '$.a' COLUMNS (item numeric PATH '$' omit quotes, item1 numeric PATH '$' omit quotes)) \watch count=5 242.586 ms --------------------------------- overall, json_value is faster than json_query. but json_value can not deal with arrays in some cases. but as you can see, in some cases, json_value and json_query are not as fast as our current implementation. Here I only test simple nested levels. if you extra multiple values from jsonb to sql type, then json_table is faster. In almost all cases, json_table is faster. json_table is actually called json_value_op, json_query_op under the hood. Without json_value and json_query related code, json_table cannot be implemented.