【发布时间】:2020-10-14 15:00:05
【问题描述】:
如何避免不必要的 CPU 开销?
见this historic question with failure tests。示例:j->'x' 是表示数字的 JSONb,j->'y' 是布尔值。从 JSONb 的第一个版本(2014 年发布 9.4)到今天(6 年!),随着 PostgreSQL v12... 似乎我们需要强制双重转换:
-
丢弃
j->'x'“binary JSONb number”信息,转换成可打印字符串j->>'x';
丢弃j->'y'“binary JSONb boolean”信息,转换成可打印字符串j->>'y'。 -
通过转换字符串
(j->>'x')::float AS x来解析字符串以获得“二进制SQL浮点数”;
通过转换字符串(j->>'y')::boolean AS y解析字符串以获得“二进制SQL布尔值”。
程序员是否没有语法或优化函数强制执行直接转换?
我没有看到 in the guide... 或者它从未实现过:是否存在技术障碍?
关于我们需要它的典型场景的说明
(响应 cmets)
想象一个场景,您的系统需要存储许多小数据集 (real example!)使用最少的磁盘,并通过集中控制/元数据/等进行管理。 JSONb 是一个很好的解决方案,并且提供了至少 2 个很好的替代方案来存储在数据库中:
- 元数据(带有架构描述符)和array of arrays 中的所有数据集;
- 在两个表中分隔元数据和表行。
(以及将元数据转换为text[] 等缓存的变体)
Alternative-1,单片,最适合“最小磁盘使用”要求,完整信息速度更快检索。当表 Alt2_DatasetLine 也有多个列(如 time)用于时间序列时,Alternative-2 可以是随机访问或部分检索的选择。
例如,您可以在单独的架构中创建所有 SQL VIEWS
CREATE mydatasets.t1234 AS
SELECT (j->>'d')::date AS d, j->>'t' AS t, (j->>'b')::boolean AS b,
(j->>'i')::int AS i, (j->>'f')::float AS f
FROM (
select jsonb_array_elements(j_alldata) j FROM Alt1_AllDataset
where dataset_id=1234
) t
-- or FROM alt2...
;
CREATE VIEW 可以自动运行 SQL 字符串 dynamically ...我们可以通过简单的格式化规则重现上述“稳定模式转换”,从元数据中提取:
SELECT string_agg( CASE
WHEN x[2]!='text' THEN format(E'(j->>\'%s\')::%s AS %s',x[1],x[2],x[1])
ELSE format(E'j->>\'%s\' AS %s',x[1],x[1])
END, ',' ) as x2
FROM (
SELECT regexp_split_to_array(trim(x),'\s+') x
FROM regexp_split_to_table('d date, t text, b boolean, i int, f float', ',') t1(x)
) t2;
...这是一个“现实生活场景”,这种(显然丑陋的)模型对于小流量应用程序来说速度惊人。除了减少磁盘使用量之外,还有其他优点:灵活性(您可以更改数据集模式而无需更改 SQL 模式)和可扩展性(2、3、... 1十亿个不同的数据集在同一张表上)。
回到问题:想象a dataset with ~50 or more columns,如果 PostgreSQL 提供“bynary to bynary cast”,SQL VIEW 会更快。
【问题讨论】:
-
你的问题到底是什么?
-
嗨@a_horse_with_no_name,我正在编辑...现在是粗体字
-
好吧,我猜这就是你为去规范化付出的代价
-
如果您可以在 JSONB 模式上创建关系视图,这意味着(至少对我而言)实际上不需要去规范化的步骤,您可以完全摆脱 JSON 部分。
-
This answer 建议
jsonb_populate_record[set]可能会跳过文本转换。
标签: postgresql casting compiler-optimization