【发布时间】:2022-05-05 23:13:04
【问题描述】:
有没有办法在 BigQuery 中列出所有表的大小?
我知道这样的命令:
select
table_id,
sum(size_bytes)/pow(10,9) as size
from
certain_dataset.__TABLES__
group by
1
但我想知道所有数据集中的所有表。
谢谢
【问题讨论】:
标签: google-bigquery
有没有办法在 BigQuery 中列出所有表的大小?
我知道这样的命令:
select
table_id,
sum(size_bytes)/pow(10,9) as size
from
certain_dataset.__TABLES__
group by
1
但我想知道所有数据集中的所有表。
谢谢
【问题讨论】:
标签: google-bigquery
目前无法在单个查询中执行此操作,但您可以使用脚本来执行此操作,这是我打印出列表的 python 脚本:
from google.cloud import bigquery
client = bigquery.Client()
datasets = list(client.list_datasets())
project = client.project
if datasets:
print('Datasets in project {}:'.format(project))
for dataset in datasets: # API request(s)
print('Dataset: {}'.format(dataset.dataset_id))
query_job = client.query("select table_id, sum(size_bytes)/pow(10,9) as size from `"+dataset.dataset_id+"`.__TABLES__ group by 1")
results = query_job.result()
for row in results:
print("\tTable: {} : {}".format(row.table_id, row.size))
else:
print('{} project does not contain any datasets.'.format(project))
【讨论】:
随着 2020 年将动态 SQL 引入 BigQuery 脚本,这个问题变得更容易了。现在,我们可以动态构建查询并通过 EXECUTE IMMEDIATE 执行它。
对于所有数据集都在 region-us 中的大多数情况,这样的事情都可以做到:
DECLARE dataset_names ARRAY<STRING>;
SET dataset_names = (
SELECT ARRAY_AGG(SCHEMA_NAME) FROM `region-us.INFORMATION_SCHEMA.SCHEMATA`
);
EXECUTE IMMEDIATE (
SELECT STRING_AGG(
(SELECT """
SELECT project_id, dataset_id, table_id, row_count, size_bytes
FROM `""" || s ||
""".__TABLES__`"""),
" UNION ALL ")
FROM UNNEST(dataset_names) AS s);
如果有大量数据集,则在尝试同时读取所有元数据时可能会返回速率限制错误。
如果发生这种情况,那么我们可以使用“批处理”方法,这种方法读取起来有点复杂,速度较慢/效率较低,但仍能完成工作:
DECLARE dataset_names ARRAY<STRING>;
DECLARE batch ARRAY<STRING>;
DECLARE batch_size INT64 DEFAULT 25;
CREATE TEMP TABLE results (
project_id STRING,
dataset_id STRING,
table_id STRING,
row_count INT64,
size_bytes INT64
);
SET dataset_names = (
SELECT ARRAY_AGG(SCHEMA_NAME)
FROM `region-us.INFORMATION_SCHEMA.SCHEMATA`
);
LOOP
IF ARRAY_LENGTH(dataset_names) < 1 THEN
LEAVE;
END IF;
SET batch = (
SELECT ARRAY_AGG(d)
FROM UNNEST(dataset_names) AS d WITH OFFSET i
WHERE i < batch_size);
EXECUTE IMMEDIATE (
SELECT """INSERT INTO results """
|| STRING_AGG(
(SELECT """
SELECT project_id, dataset_id, table_id, row_count, size_bytes
FROM `""" || s || """.__TABLES__`"""),
" UNION ALL ")
FROM UNNEST(batch) AS s);
SET dataset_names = (
SELECT ARRAY_AGG(d)
FROM UNNEST(dataset_names) AS d
WHERE d NOT IN (SELECT * FROM UNNEST(batch)));
END LOOP;
SELECT * FROM results;
【讨论】:
如果您想要一个可以抓取所有表并捕获所有元数据(例如列类型、表大小、描述等)的 python 脚本,我的 github 帐户上有一个脚本可以执行此操作。
它会根据您的需要将输出保存到 Bigquery 表、CSV 或 JSON。
我为一位必须审核数万张表但我用来在公共数据集中查找特定表特征的客户创建了这个。
https://github.com/go-dustin/gcp_data_utilities/tree/master/BigQuery/meta_data_crawler
【讨论】:
from google.cloud import bigquery
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "YOURGCPSERVICEACCOUNTKEY.json"
GCP_PROJECT_ID = "YOURGCPPROJECT"
client = bigquery.Client(project=GCP_PROJECT_ID)
datasets = list(client.list_datasets())
project = client.project
if datasets:
print('Datasets in project {}:'.format(project))
for dataset in datasets: # API request(s)
print('Dataset: {}'.format(dataset.dataset_id))
query_job = client.query(
f"""
SELECT
table_id,
size_bytes/pow(1024,3) AS size_GB,
FROM `{GCP_PROJECT_ID}.{dataset.dataset_id}`.__TABLES__
"""
)
results = query_job.result()
for row in results:
print(f"\tTable: {row.table_id} : {row.size_GB} GB")
else:
print('project does not contain any datasets.'.format(project))
回复@Alex 的答案,这个答案将获得更准确的 GB 大小数字。 1kb 应该表示为 1024 字节
【讨论】:
这可以通过需要输入字符串的EXECUTE IMMEDIATE 来完成。
请注意,您需要设置数据集所在的正确区域,在我的情况下为eu:
DECLARE dataset_names ARRAY<STRING>;
DECLARE query_first_part STRING;
SET dataset_names = (SELECT ARRAY_AGG(SCHEMA_NAME) FROM `region-eu.INFORMATION_SCHEMA.SCHEMATA`);
SET query_first_part = """
SELECT
project_id,
dataset_id,
table_id,
size_bytes / pow(1024, 3) size_gb,
FROM `""";
EXECUTE IMMEDIATE (
SELECT
STRING_AGG(
query_first_part || dataset_name || ".__TABLES__`",
" UNION ALL "
)
FROM UNNEST(dataset_names) AS dataset_name
);
更多信息EXECUTE IMMEDIATE:
https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate
【讨论】: