Google BigQuery неполный запрос отвечает на нечетные попытки

При запросе BigQuery через API Python с использованием:

service.jobs().getQueryResults

Мы обнаруживаем, что первая попытка работает нормально — все ожидаемые результаты включены в ответ. Однако, если запрос выполняется второй раз вскоре после первого (примерно в течение 5 минут), почти мгновенно возвращается только небольшое подмножество результатов (в степени 2) без ошибок.

См. наш полный код по адресу: https://github.com/sean-schaefer/pandas/blob/master/pandas/io/gbq.py

Любые мысли о том, что может быть причиной этого?


person Jacob Schaer    schedule 19.07.2013    source источник


Ответы (1)


Похоже, проблема в том, что мы возвращаем разное количество строк по умолчанию для query() и getQueryResults(). Таким образом, в зависимости от того, быстро ли завершился ваш запрос (и поэтому вам не нужно было использовать getQueryResults()), вы либо получили больше, либо меньше строк.

Я зарегистрировал ошибку, и скоро мы должны ее исправить.

Обходной путь (и в целом хорошая идея) состоит в том, чтобы установить maxResults как для запроса, так и для вызовов getQueryResults. И если вам нужно много строк, вы можете просмотреть результаты, используя возвращаемый токен страницы.

Ниже приведен пример чтения одной страницы данных из завершенного задания запроса. Он будет включен в следующий выпуск bq.py:

class _JobTableReader(_TableReader):
  """A TableReader that reads from a completed job."""

  def __init__(self, local_apiclient, project_id, job_id):
    self.job_id = job_id
    self.project_id = project_id
    self._apiclient = local_apiclient

  def ReadSchemaAndRows(self, max_rows=None):
    """Read at most max_rows rows from a table and the schema.

    Args:
      max_rows: maximum number of rows to return.

    Raises:
      BigqueryInterfaceError: when bigquery returns something unexpected.

    Returns:
      A tuple where the first item is the list of fields and the
      second item a list of rows.
    """
    page_token = None
    rows = []
    schema = {}
    max_rows = max_rows if max_rows is not None else sys.maxint
    while len(rows) < max_rows:
      (more_rows, page_token, total_rows, current_schema) = self._ReadOnePage(
          max_rows=max_rows - len(rows),
          page_token=page_token)
      if not schema and current_schema:
        schema = current_schema.get('fields', {})

      max_rows = min(max_rows, total_rows)
      for row in more_rows:
        rows.append([entry.get('v', '') for entry in row.get('f', [])])
      if not page_token and len(rows) != max_rows:
          raise BigqueryInterfaceError(
            'PageToken missing for %r' % (self,))
      if not more_rows and len(rows) != max_rows:
        raise BigqueryInterfaceError(
            'Not enough rows returned by server for %r' % (self,))
    return (schema, rows)

  def _ReadOnePage(self, max_rows, page_token=None):
    data = self._apiclient.jobs().getQueryResults(
        maxResults=max_rows,
        pageToken=page_token,
        # Sets the timeout to 0 because we assume the table is already ready.
        timeoutMs=0,
        projectId=self.project_id,
        jobId=self.job_id).execute()
    if not data['jobComplete']:
      raise BigqueryError('Job %s is not done' % (self,))
    page_token = data.get('pageToken', None)
    total_rows = int(data['totalRows'])
    schema = data.get('schema', None)
    rows = data.get('rows', [])
    return (rows, page_token, total_rows, schema)
person Jordan Tigani    schedule 19.07.2013
comment
У вас есть пример использования токена страницы? Мы нашли страницу документации: developers.google.com/bigquery/docs/data#paging , но в нем не было примеров кода. Это кажется важным для нашего кода, поскольку максимальное количество результатов на странице жестко ограничено. - person Jacob Schaer; 22.07.2013
comment
Кроме того, это ошибка API или ошибка бэкэнда? Кажется, она все еще у нас есть, так что нам нужно будет загрузить более новую версию, когда это будет завершено? - person Jacob Schaer; 25.07.2013
comment
Исправление полностью на бэкэнде BigQuery. Он должен был выйти в эфир вчера. - person Jordan Tigani; 26.07.2013
comment
Если вы все еще наблюдаете неожиданное поведение, можете ли вы указать идентификаторы заданий запросов? - person Jordan Tigani; 26.07.2013
comment
Вчера казалось, что у нас все еще есть проблема, хотя в настоящее время мы не выводим идентификаторы вакансий. Мы можем внести изменения и вернуться к вам по этому вопросу. А пока нас все еще интересует, есть ли какие-либо примеры использования пейджинга в python. - person Jacob Schaer; 26.07.2013
comment
В качестве дополнения мы не смогли определить идентификаторы заданий, которые вызывали проблемы. Мы также запустили несколько запросов функций в BigQuery, но, похоже, этому не уделяется много внимания. Есть ли лучшее место, чтобы положить их? В частности, мы все еще хотели бы увидеть пример Python для разбиения на страницы: code.google.com/p/google-bigquery/issues/detail?id=32 - person Jacob Schaer; 01.08.2013
comment
Я добавил в свой ответ пример подкачки python. - person Jordan Tigani; 06.08.2013
comment
Извините, что это было давно - другой проект, над которым мы работали, получил приоритет. Вы сказали, что это будет включено в проект bq.py (предположительно, в bigquery_client.py) — будет ли это дополнением к существующему методу BigqueryClient.ReadTableRows() или будет заменена функциональность? И вообще, есть идеи, когда будет следующий релиз? В свете значительного количества проблем с API, которые у нас были, мы рассматриваем возможность изменения нашего модуля pandas, чтобы просто расширить bq.py. Одна проблема, с которой мы столкнулись, заключается в том, что ReadTableRows(), по-видимому, не имеет каких-либо возможностей пакетной обработки, как и BigQuery SQL. - person Jacob Schaer; 25.08.2013
comment
BigQuery поддерживает пакетную обработку запросов API (хотя и не обязательно пакетную обработку операторов SQL). Необработанная поддержка описана здесь: developers.google.com/storage. /docs/json_api/v1/how-tos/batch. Я могу опубликовать образец Python, но он слишком длинный для этого блока комментариев — если вам интересно, задайте еще один вопрос на высшем уровне? - person Jordan Tigani; 26.08.2013
comment
Ну, я не имел в виду такую ​​пакетную обработку - я имел в виду, как в MySQL SELECT {x} LIMIT {start}, {finish}, где вы можете увеличивать {start}, {finish}. Кроме того, я пытался работать с вашим примером кода, и мне не очень повезло. Я постоянно получаю: TypeError: получил неожиданный аргумент ключевого слова pageToken Когда я пытаюсь определить «данные», как вы сделали в своем примере. Я также заметил, что ваш класс реализует _TableReader, который я не могу найти в текущем API. - person Jacob Schaer; 27.08.2013
comment
Аргумент pageToken должен быть доступен в jobs.getQueryResults(). См. pydoc здесь: google-api-client-libraries.appspot.com/documentation/bigquery/ - person Jordan Tigani; 27.08.2013
comment
Мне очень не хочется воскрешать такой старый поток, как этот, но у нас есть похожие проблемы в этом потоке: stackoverflow.com/questions/19145587/bq-py-not-paging-results У нас был первоначальный отзыв от кого-то по имени Эрик, но с тех пор мы ничего не слышали. В конечном итоге оба они связаны с пейджингом, так что, может быть, вы могли бы взглянуть? Опять же, мне очень не нравится использовать стек таким образом, но согласно developers.google.com/bigquery /support Это ваш официальный портал поддержки. - person Jacob Schaer; 08.10.2013
comment
Эрик входит в команду BigQuery. Насколько я понимаю, он выпускает новую версию bq.py, которая устраняет проблему. Я свяжусь с ним и попрошу его обновить другой вопрос. - person Jordan Tigani; 09.10.2013