【问题标题】:how to list ALL table sizes in a project如何列出项目中的所有表格大小
【发布时间】: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


    【解决方案1】:

    目前无法在单个查询中执行此操作,但您可以使用脚本来执行此操作,这是我打印出列表的 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))
    

    【讨论】:

    • 你好,亚历克斯。您如何提供此代码的凭据?当我点击这一行时,'client = bigquery.Client()',我收到这条消息,'DefaultCredentialsError:无法自动确定凭据。请设置 GOOGLE_APPLICATION_CREDENTIALS 或显式创建凭据并重新运行应用程序。欲了解更多信息,请参阅developers.google.com/accounts/docs/…。谢谢。
    • 哦,我知道它是如何工作的。您创建一个 .json 文件并像这样引用它:client = bigquery.Client.from_service_account_json('C:/your_path_here.123456789.json')
    【解决方案2】:

    随着 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;
    

    【讨论】:

      【解决方案3】:

      如果您想要一个可以抓取所有表并捕获所有元数据(例如列类型、表大小、描述等)的 python 脚本,我的 github 帐户上有一个脚本可以执行此操作。

      它会根据您的需要将输出保存到 Bigquery 表、CSV 或 JSON。

      我为一位必须审核数万张表但我用来在公共数据集中查找特定表特征的客户创建了这个。

      https://github.com/go-dustin/gcp_data_utilities/tree/master/BigQuery/meta_data_crawler

      【讨论】:

        【解决方案4】:
        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 字节

        【讨论】:

          【解决方案5】:

          这可以通过需要输入字符串的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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-04-29
            • 1970-01-01
            • 2013-04-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多