【问题标题】:Whitespace causes problem in BigQuery with Python空格在 Python 的 BigQuery 中导致问题
【发布时间】:2020-05-20 17:30:22
【问题描述】:

我有以下 Python 代码来检索 BigQuery 数据集。然后我在 Jupyter Notebook on kaggle 上执行两个查询 working_querybad_query。 唯一的区别是在第 3 行之后添加了空格 ...posts_questions` as q 这使得 bad_query 失败并显示消息

Query exceeded limit for bytes billed: 10000000000. 24460132352 or higher required.

我知道成本控制已启用,但不知道这可能是这里的问题。 以后如何避免此类陷阱,有人可以解释这个问题吗?

from google.cloud import bigquery

client = bigquery.Client()
dataset_ref = client.dataset("stackoverflow", project="bigquery-public-data")
dataset = client.get_dataset(dataset_ref)

safe_config = bigquery.QueryJobConfig(maximum_bytes_billed=10**10)

answers_query_job = client.query(working_query, job_config=safe_config) 
answers_query_job.to_dataframe()

working_query = """
                SELECT a.id, a.body, a.owner_user_id
                FROM `bigquery-public-data.stackoverflow.posts_answers` AS a
                INNER JOIN `bigquery-public-data.stackoverflow.posts_questions` AS q
                    ON q.id = a.parent_id
                WHERE q.tags LIKE '%bigquery%'
                """
bad_query = """
                SELECT a.id, a.body, a.owner_user_id
                FROM `bigquery-public-data.stackoverflow.posts_answers` AS a
                INNER JOIN `bigquery-public-data.stackoverflow.posts_questions` AS q 
                    ON q.id = a.parent_id
                WHERE q.tags LIKE '%bigquery%'
                """

更新:

这是一个缓存问题,因为 working_query 在激活成本控制之前运行。这样,即使启用了成本控制,它也可以从缓存中检索数据。 查询必须完全相同才能共享缓存,因此即使添加空格也可以防止这种情况发生。

【问题讨论】:

    标签: python sql caching google-bigquery whitespace


    【解决方案1】:

    我已经使用您的两个查询执行了一些测试,并且它们以相同的方式执行。

    首先,我必须指出,query() 方法接收一个字符串,job_config 用于配置作业。此外,文档没有提及与您的查询字符串中的额外空格相关的任何问题,here.

    此外,如果您导航到 BigQuery 用户界面,一次复制并粘贴一个查询并执行它,您将在 Job Information 下看到这两个查询将处理大约 23Gb 的数据,并且相同数量的数据将是计费的字节数。因此,如果您设置了bigquery.QueryJobConfig(maximum_bytes_billed=23000000000) 并且省略了to_dataframe() 方法,那么上述两个查询都将完美运行。

    更新

    根据documentation,默认情况下您将use_query_cache 设置为true,这意味着如果您运行相同的查询,它将从前一个查询中检索结果。因此,不会处理任何字节。如果您之前在没有设置 maximum_bytes_billed 的情况下运行查询。然后您以最大数量运行相同的查询,即使查询将运行,它处理的比您现在设置的要多。

    在您的例子中,我使用 AI Platform 中的 Python 3 Notebook 和 Shell 中的 .py 文件来运行以下代码。

    第一个代码,

    from google.cloud import bigquery
    import pandas
    
    client = bigquery.Client()
    dataset_ref = client.dataset("stackoverflow", project="bigquery-public-data")
    dataset = client.get_dataset(dataset_ref)
    
    job_config = bigquery.QueryJobConfig(maximum_bytes_billed=10**10)
    job_config.use_query_cache = False
    
    working_query = """
                    SELECT a.id, a.body, a.owner_user_id
                    FROM `bigquery-public-data.stackoverflow.posts_answers` AS a
                    INNER JOIN `bigquery-public-data.stackoverflow.posts_questions` AS q
                        ON q.id = a.parent_id
                    WHERE q.tags LIKE '%bigquery%'
                    """
    answers_query_job = client.query(working_query, job_config) 
    answers_query_job.to_dataframe()
    

    第二个代码,

    from google.cloud import bigquery
    import pandas
    
    client = bigquery.Client()
    dataset_ref = client.dataset("stackoverflow", project="bigquery-public-data")
    dataset = client.get_dataset(dataset_ref)
    
    job_config = bigquery.QueryJobConfig(maximum_bytes_billed=10**10)
    job_config.use_query_cache = False
    
    
    bad_query = """
                    SELECT a.id, a.body, a.owner_user_id
                    FROM `bigquery-public-data.stackoverflow.posts_answers` AS a
                    INNER JOIN `bigquery-public-data.stackoverflow.posts_questions` AS q 
                        ON q.id = a.parent_id
                    WHERE q.tags LIKE '%bigquery%'
                    """
    
    answers_query_job = client.query(working_query, job_config) 
    answers_query_job.to_dataframe()
    

    以上代码均无效。他们导致错误:

    Query exceeded limit for bytes billed: 10000000000. 24460132352 or higher required.
    

    另一方面,如果设置了job_config = bigquery.QueryJobConfig(maximum_bytes_billed=25000000000)。两个查询都运行正常。

    【讨论】:

    • 我想启用成本控制,但不知道为什么空格或其他任何内容会触发此行为。
    • @glykocalyx,该查询将处理 23Gb 的数据,并将在设置为最大值的 10**10 以上计费。因此,不会运行任何查询。我已经使用 shell 复制了它,但没有一个使用这个最大集。另一方面,如果将其设置为 bigquery.QueryJobConfig(maximum_bytes_billed=23000000000) 并注释 to_dataframe(),则两者都会运行。它们处理的数据量相同,您可以在 BigQuery UI 的作业详细信息下看到。
    • “working_query”仍然会从 kaggle notebook 运行。问题是,为什么?
    • @glykocalyx,您可能已启用缓存结果。因此,您运行了一次查询,没有设置最大限制,然后当您再次运行时,使用了缓存的结果。与查询字符串中的额外空间无关。我已经在 AI Platform 中使用 shell 和 Notebook 重现了您的案例,如果您设置正确的 total_bytes_billed,这两个查询都可以正常工作。我已经更新了我的答案,对我的复制进行了更详细的解释。
    • 可能是kaggle notebook,我会朝这个方向多看。
    【解决方案2】:

    您可能启用了成本控制:documentation

    此错误表示您的查询将要扫描的字节数超过“计费的最大字节数”中设置的限制。

    你能可靠地重现这个错误吗?查询中的空格看起来与 BigQueryrols 中的 cost cont 没有任何关系。当数据较大或引入成本控制时,这可能只是巧合。

    编辑:Alexandre 的回答是正确的——“好查询”成功了,因为它从缓存中获取结果。刚刚重试(注意use_query_cache,而不是上面评论线程中的UseQueryCache)

    safe_config = bigquery.QueryJobConfig(maximum_bytes_billed=10**10, use_query_cache=False)
    

    对于好的查询也有同样的错误。此外,您可以检查结果作业中的 cache_hit 以查看是否从缓存中获取响应。只要查询成功,就等于true:

    print("Cache hit: ")
    print(answers_query_job.cache_hit)
    

    【讨论】:

    • 感谢您的回复,我知道成本控制已启用,问题是为什么空格会触发此行为?这是我笔记本的链接,是的,它是可重现的,请参阅kaggle notebook
    • 这确实是 Alexandre 在他的回复中提到的查询缓存问题 - 我刚刚使用 use_query_cache=False 重试了您的笔记本,我看到了同样的错误
    • 更新了回复,很遗憾我无法对您上面的评论帖发表评论。 Alexandre Moraes 是在正确的轨道上,只是应该使用 use_query_cache=True 而不是 UseQueryCache。请参阅此处的文档:cloud.google.com/bigquery/docs/cached-results#python
    • 是的。 working_query 没有任何成本,因为它只是从缓存中加载数据。因此,无论您在那里设置什么,它都不受成本控制的影响。因为它是免费的。由于成本控制,bad_query 总是失败。如果,为了实验,你可以在关闭成本控制的情况下运行 bad_query,它也会有缓存值,如果重试,同样会开始成功。引用文档:“要从缓存中检索数据,重复的查询文本必须与原始查询完全相同。”。所以即使添加空格也会导致缓存失效。
    • 你说得对,刚刚做了实验,结果如你所说。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    相关资源
    最近更新 更多