取消嵌套 BigQuery 和 BigTable 中的大量列
Unnesting a big quantity of columns in BigQuery and BigTable
我在 BigTable 中有一个 table,只有一个列族,包含一些主要数据。我正在按照 Google 云指南从 BigTable (https://cloud.google.com/bigquery/external-data-bigtable) 查询 BigTable 数据,到目前为止一切顺利。
我已经创建了 table 定义文件,就像所需的文档一样:
{
"sourceFormat": "BIGTABLE",
"sourceUris": [
"https://googleapis.com/bigtable/projects/{project_id}/instances/{instance_id}/tables/{table_id}"
],
"bigtableOptions": {
"readRowkeyAsString": "true",
"columnFamilies": [
{
"familyId": "leads",
"columns": [
{
"qualifierString": "Id",
"type": "STRING"
},
{
"qualifierString": "IsDeleted",
"type": "STRING"
},
...
]
}
]
}
}
但随后,事情开始向南发展......
这是 BigQuery“table”最终的样子:
每一行都是一个行键,每一列内都有一个嵌套单元格,我需要的唯一值是 leads.Id.cell
中的 value
(在本例中)
经过一番搜索,我找到了解决方法:
所以在我的情况下它会是这样的:
SELECT
ARRAY_TO_STRING(ARRAY(SELECT value FROM UNNEST(leads.Id.cell)), "") AS Id,
...
FROM xxx
问题是我正在处理一个每行超过 600 列的数据集。每个 row/query.
重复此过程超过 600 次是不可行的(并且不可能,考虑到 BigQuery 的子查询限制)
我想不出一种方法来自动执行此查询,甚至想不出其他方法来解除这么多单元格的嵌套(我的 SQL 知识到此为止)。
有没有什么方法可以使用 SQL/BigQuery 查询对 600 多列进行这样的取消测试?以更有效的方式更可取?如果没有,我正在考虑使用从 BigTable 到 BigQuery 的简单 Python 连接器进行每日批处理,但我担心这会产生费用。
任何文档、参考或想法将不胜感激。
谢谢。
一般来说,当您尝试使用 SQL 查询 NoSQL 数据库(如 BigTable)时,您将陷入痛苦的境地。取消嵌套数据在 SQL 中是一项非常昂贵的操作,因为每次调用 UNNEST 时你都在有效地执行交叉连接(即 many-to-many),所以尝试这样做 600 多次会给你一个查询超时或巨额账单。
BigTable API 将比 SQL 更有效,因为它旨在查询 NoSQL 结构。一个常见的模式是每天运行一个脚本(例如 Cloud Functions 中的 Python 脚本)并使用 API 获取当天的数据,解析它,然后将其输出到文件在云存储中。然后您可以根据需要通过 BigQuery 查询这些文件。循环遍历所有数据列而不需要大量数据转换的每日脚本通常很便宜,而且绝对比试图强制它通过 SQL.
更便宜
也就是说,如果您真的打算使用 SQL,您也许可以使用 BigQuery 的 JSON functions 来提取您需要的嵌套数据。如果没有示例数据,很难想象您的数据结构是什么,但您可以将整行作为 JSON 的单列或字符串来读取。然后,如果您有要提取的值的 predictable 路径,则可以使用 JSON_EXTRACT_STRING_ARRAY 之类的函数将所有这些值提取到一个数组中。 Regex 函数也可以类似地使用。但是如果你需要在整体上做这种解析table才能查询,那么先进行数据转换的批处理作业仍然会更有效率。
我在 BigTable 中有一个 table,只有一个列族,包含一些主要数据。我正在按照 Google 云指南从 BigTable (https://cloud.google.com/bigquery/external-data-bigtable) 查询 BigTable 数据,到目前为止一切顺利。
我已经创建了 table 定义文件,就像所需的文档一样:
{
"sourceFormat": "BIGTABLE",
"sourceUris": [
"https://googleapis.com/bigtable/projects/{project_id}/instances/{instance_id}/tables/{table_id}"
],
"bigtableOptions": {
"readRowkeyAsString": "true",
"columnFamilies": [
{
"familyId": "leads",
"columns": [
{
"qualifierString": "Id",
"type": "STRING"
},
{
"qualifierString": "IsDeleted",
"type": "STRING"
},
...
]
}
]
}
}
但随后,事情开始向南发展......
这是 BigQuery“table”最终的样子:
每一行都是一个行键,每一列内都有一个嵌套单元格,我需要的唯一值是 leads.Id.cell
中的 value
(在本例中)
经过一番搜索,我找到了解决方法:
所以在我的情况下它会是这样的:
SELECT
ARRAY_TO_STRING(ARRAY(SELECT value FROM UNNEST(leads.Id.cell)), "") AS Id,
...
FROM xxx
问题是我正在处理一个每行超过 600 列的数据集。每个 row/query.
重复此过程超过 600 次是不可行的(并且不可能,考虑到 BigQuery 的子查询限制)我想不出一种方法来自动执行此查询,甚至想不出其他方法来解除这么多单元格的嵌套(我的 SQL 知识到此为止)。
有没有什么方法可以使用 SQL/BigQuery 查询对 600 多列进行这样的取消测试?以更有效的方式更可取?如果没有,我正在考虑使用从 BigTable 到 BigQuery 的简单 Python 连接器进行每日批处理,但我担心这会产生费用。
任何文档、参考或想法将不胜感激。
谢谢。
一般来说,当您尝试使用 SQL 查询 NoSQL 数据库(如 BigTable)时,您将陷入痛苦的境地。取消嵌套数据在 SQL 中是一项非常昂贵的操作,因为每次调用 UNNEST 时你都在有效地执行交叉连接(即 many-to-many),所以尝试这样做 600 多次会给你一个查询超时或巨额账单。
BigTable API 将比 SQL 更有效,因为它旨在查询 NoSQL 结构。一个常见的模式是每天运行一个脚本(例如 Cloud Functions 中的 Python 脚本)并使用 API 获取当天的数据,解析它,然后将其输出到文件在云存储中。然后您可以根据需要通过 BigQuery 查询这些文件。循环遍历所有数据列而不需要大量数据转换的每日脚本通常很便宜,而且绝对比试图强制它通过 SQL.
更便宜也就是说,如果您真的打算使用 SQL,您也许可以使用 BigQuery 的 JSON functions 来提取您需要的嵌套数据。如果没有示例数据,很难想象您的数据结构是什么,但您可以将整行作为 JSON 的单列或字符串来读取。然后,如果您有要提取的值的 predictable 路径,则可以使用 JSON_EXTRACT_STRING_ARRAY 之类的函数将所有这些值提取到一个数组中。 Regex 函数也可以类似地使用。但是如果你需要在整体上做这种解析table才能查询,那么先进行数据转换的批处理作业仍然会更有效率。