Snowflake JSON 尝试获取不同值时出现未知关键字错误
Snowflake JSON unknown keyword error when trying to get distinct values
我在 Snowflake 中有一个 table,其中一个名为 'value' 的字段有时是纯文本有时 JSON,该字段在 Snowflake[=20= 中存储为字符串]
我创建此视图是为了仅获取具有 Json 格式的行
CREATE OR REPLACE VIEW tmp_events AS
SELECT PARSE_JSON(value) as json_data,
id
FROM SessionEvent
WHERE session_event_type_id=7;
然后我将行展平以创建一个新字段
CREATE OR REPLACE VIEW tmp_events_step2 AS
SELECT id,
json_data:meta:selected::string AS choice
from tmp_events ,
LATERAL FLATTEN(input => tmp_events.json_data)
WHERE choice IS NOT NULL
一切运行到现在都很好,我可以从这两个视图预览数据,没有错误,我得到了我期待的结果。
当我尝试从 choice 中获取不同的值时出现错误
SELECT DISTINCT choice from tmp_events_step2;
Error parsing JSON: unknown keyword "brain", pos 6
这个名字 Brain 似乎来自我最初的 table 没有 WHERE
声明。
如果我运行没有DISTINCT
的查询就没有错误。
我在尝试调试时注意到的一件奇怪的事情:当我在 tmp_events_step2
中设置一个限制时,代码再次正常工作,即使我设置的限制大于 [=43] 中的行数=]
CREATE OR REPLACE VIEW tmp_events_step2 AS
SELECT id,
json_data:meta:selected::string AS choice
from tmp_events ,
LATERAL FLATTEN(input => tmp_events.json_data)
WHERE choice IS NOT NULL
LIMIT 10000000;
SELECT DISTINCT choice from tmp_events_step2;
有什么收获?为什么它只对限制有效?
请针对此问题提交支持案例。
对此的非常简单的答案是内置函数 TRY_PARSE_JSON()
呃,不是。您似乎对查询优化器有问题,可能会执行不正确的谓词下推。防止优化器这样做的一种方法是使用安全视图选项:
CREATE SECURE VIEW tmp_events_step2 ...
并提交支持请求...
我们在两年前报告了这个错误,他们说他们不会修复,因为通过在 运行 之前提升 JSON 访问权限,WHERE 子句中的过滤器使强制转换 valid/safe,影响性能。
create table variant_cast_bug(num number, var variant);
insert into variant_cast_bug
select column1 as num, parse_json(column2) as var
from values (1, '{"id": 1}'),
(1, '{"id": 2}'),
(2, '{"id": "text"}')
v;
select * from variant_cast_bug;
select var:id from variant_cast_bug;
select var:id from variant_cast_bug where num = 1;
select var:id::number from variant_cast_bug where num = 1; -- <- broken
select TRY_TO_NUMBER(var:id) from variant_cast_bug where num = 1; -- <- works
有时你可以嵌套 select 它会起作用,然后你可以在它周围添加另一个 SELECT 层,并进行一些聚合,成本再次爆炸。
正如 Hans 提到的那样,仅有的两个安全解决方案是 SERCURE VIEW
,但这是一个性能噩梦。
或者了解这个问题,用TRY_TO_NUMBER或者它的朋友。
当时情况变得更糟,因为 JSON 布尔值无法传递给 TRY_TO_BOOLEAN..
有一次我们被这个问题困扰是在雪花发布之后,当时已经 运行 一年的代码开始出现这个错误,因为它足够复杂,提升没有影响,并且然后在发布后它做到了。这是 Snowflake 相当敏感的地方,然后回滚了版本,我们将 TRY_TO 放在已经工作的 SQL 上,只是为了安全起见。
我在 Snowflake 中有一个 table,其中一个名为 'value' 的字段有时是纯文本有时 JSON,该字段在 Snowflake[=20= 中存储为字符串]
我创建此视图是为了仅获取具有 Json 格式的行
CREATE OR REPLACE VIEW tmp_events AS
SELECT PARSE_JSON(value) as json_data,
id
FROM SessionEvent
WHERE session_event_type_id=7;
然后我将行展平以创建一个新字段
CREATE OR REPLACE VIEW tmp_events_step2 AS
SELECT id,
json_data:meta:selected::string AS choice
from tmp_events ,
LATERAL FLATTEN(input => tmp_events.json_data)
WHERE choice IS NOT NULL
一切运行到现在都很好,我可以从这两个视图预览数据,没有错误,我得到了我期待的结果。
当我尝试从 choice 中获取不同的值时出现错误
SELECT DISTINCT choice from tmp_events_step2;
Error parsing JSON: unknown keyword "brain", pos 6
这个名字 Brain 似乎来自我最初的 table 没有 WHERE
声明。
如果我运行没有DISTINCT
的查询就没有错误。
我在尝试调试时注意到的一件奇怪的事情:当我在 tmp_events_step2
中设置一个限制时,代码再次正常工作,即使我设置的限制大于 [=43] 中的行数=]
CREATE OR REPLACE VIEW tmp_events_step2 AS
SELECT id,
json_data:meta:selected::string AS choice
from tmp_events ,
LATERAL FLATTEN(input => tmp_events.json_data)
WHERE choice IS NOT NULL
LIMIT 10000000;
SELECT DISTINCT choice from tmp_events_step2;
有什么收获?为什么它只对限制有效?
请针对此问题提交支持案例。
对此的非常简单的答案是内置函数 TRY_PARSE_JSON()
呃,不是。您似乎对查询优化器有问题,可能会执行不正确的谓词下推。防止优化器这样做的一种方法是使用安全视图选项:
CREATE SECURE VIEW tmp_events_step2 ...
并提交支持请求...
我们在两年前报告了这个错误,他们说他们不会修复,因为通过在 运行 之前提升 JSON 访问权限,WHERE 子句中的过滤器使强制转换 valid/safe,影响性能。
create table variant_cast_bug(num number, var variant);
insert into variant_cast_bug
select column1 as num, parse_json(column2) as var
from values (1, '{"id": 1}'),
(1, '{"id": 2}'),
(2, '{"id": "text"}')
v;
select * from variant_cast_bug;
select var:id from variant_cast_bug;
select var:id from variant_cast_bug where num = 1;
select var:id::number from variant_cast_bug where num = 1; -- <- broken
select TRY_TO_NUMBER(var:id) from variant_cast_bug where num = 1; -- <- works
有时你可以嵌套 select 它会起作用,然后你可以在它周围添加另一个 SELECT 层,并进行一些聚合,成本再次爆炸。
正如 Hans 提到的那样,仅有的两个安全解决方案是 SERCURE VIEW
,但这是一个性能噩梦。
或者了解这个问题,用TRY_TO_NUMBER或者它的朋友。
当时情况变得更糟,因为 JSON 布尔值无法传递给 TRY_TO_BOOLEAN..
有一次我们被这个问题困扰是在雪花发布之后,当时已经 运行 一年的代码开始出现这个错误,因为它足够复杂,提升没有影响,并且然后在发布后它做到了。这是 Snowflake 相当敏感的地方,然后回滚了版本,我们将 TRY_TO 放在已经工作的 SQL 上,只是为了安全起见。