SELECT и INSERT к таблице в Google BigQuery, включая общедоступные датасеты. Структура таблицы автоматически определяется по схеме таблицы BigQuery.
Для чтения используется REST API BigQuery (tabledata.list), поэтому доступны только нативные таблицы (представления, materialized view и внешние таблицы не поддерживаются). Для записи используются потоковые вставки (tabledata.insertAll), для которых в проекте должен быть включен биллинг.
Синтаксис
Аргументы
Аргументы
project, dataset, table и access_token также можно задавать в форме ключ = значение; позиционные аргументы заполняют эти позиции в указанном порядке. Указание аргумента одновременно как позиционного и как ключа (или одного и того же ключа дважды) приводит к ошибке.
Следующие аргументы можно задавать в форме ключ = значение (или в качестве ключей именованной коллекции):
Аутентификация
- Токен доступа. Любой действительный токен доступа OAuth 2.0, например полученный с помощью
gcloud auth print-access-token. Срок действия токенов быстро истекает (обычно через час), поэтому этот метод лучше всего подходит для интерактивного использования. - Ключ сервисного аккаунта (рекомендуется для серверов). Передайте содержимое файла ключа, созданного в Google Cloud IAM, в аргументе
service_account_key. ClickHouse подписывает JWT этим ключом и обменивает его на токен доступа, автоматически обновляя последний. - Токен обновления. Передайте
client_id,client_secretиrefresh_token, например из файла~/.config/gcloud/application_default_credentials.json, созданного после выполненияgcloud auth application-default login.
BigQuery или с помощью CREATE TABLE ... AS bigquery(...)), регистрируется как зависимость этой коллекции, поэтому DROP NAMED COLLECTION блокируется, пока существует таблица.
Сопоставление типов данных
Примечания:
DATETIMEв BigQuery не имеет часового пояса; он сопоставляется сDateTime64(6, 'UTC'), чтобы отображаемое значение не зависело от часового пояса сервера.NULLABLERECORDсопоставляется сNullable(Tuple(...)), поэтомуNULLдля всей записи сохраняется какNULL, а не схлопывается вTupleиз значений по умолчанию. Массив со значениемNULL(или пустой массив) становится пустым массивом, посколькуArrayне может находиться внутриNullableв ClickHouse. Массив BigQuery не может содержать элементыNULL(ARRAY<T>эквивалентенARRAY<T NOT NULL>), поэтому тип элемента поляREPEATEDне являетсяNullable(Array(T)илиArray(Tuple(...))для элементаRECORD); элементNULLв ответеtabledata.listотклоняется как некорректные входные данные.- Чтение и запись столбцов
Nullable(Tuple(...))через табличную функциюbigqueryработают без дополнительных настроек. Для создания постоянной таблицы с движкомBigQuery, содержащей такой столбец (независимо от того, определяется ли структура автоматически или объявляется явно), требуется настройкаenable_nullable_tuple_type, как и для любого столбцаNullable(Tuple). При явном объявлении столбцов полеRECORDможно вместо этого объявить как обычныйTuple(...), чтобы избежать этой настройки, ценой приведенияNULLвсей записи к кортежу по умолчанию; единственное допустимое отличие от автоматически определённого типа — удалитьNullable, оборачивающийTupleполяRECORD, и только для этой же записи: nullable нельзя перенести на другую запись — внутреннюю или внешнюю. GEOGRAPHYсопоставляется с Geometry. BigQuery передаёт значениеGEOGRAPHYв виде текста WKT, который при чтении разбирается в соответствующую альтернативуGeometry(VariantизPoint,MultiPoint,Ring,LineString,MultiLineString,PolygonиMultiPolygon), а при записи сериализуется обратно в WKT. ДляGEOMETRYCOLLECTIONи пустой геометрии (например,POINT EMPTY) нет соответствия вGeometry, поэтому чтение строки, содержащей такое значение, вызывает ошибку. ПосколькуVariantможет самостоятельно хранитьNULL, полеGEOGRAPHYсNULLABLEсопоставляется сGeometry, а не сNullable(Geometry), иNULLвсё равно сохраняется при записи и последующем чтении.JSONсопоставляется сString, а не с типом данных JSON, поскольку типJSONв ClickHouse принимает на верхнем уровне только объект ({...}), тогда как значениеJSONв BigQuery может быть любым значением JSON — скаляром, массивом илиnull— поэтому таблицу, содержащую такие значения, нельзя было бы прочитать. Кроме того,JSONнельзя обернуть вNullable, поэтому SQLNULLв столбцеNULLABLEне сохранялся бы. Сопоставление сStringне приводит к потере данных; объекты верхнего уровня можно преобразовать с помощьюCAST(value AS JSON).- Значения
BIGNUMERIC, содержащие более 38 цифр в целой части, не помещаются вDecimal(76, 38)и вызывают ошибку. - Значения
TIMESTAMPиDATEвне диапазонаDateTime64/Date32(годы 1900–2299) не поддерживаются. - Столбцы
RANGEдоступны только для чтения.tabledata.insertAllожидает значениеRANGE<T>в виде структурированного объекта{start, end}, который нельзя восстановить из сопоставления сString, поэтому вставка в столбецRANGEвызывает ошибку. - Значения
INT64отправляются вtabledata.insertAllкак десятичные строки, поскольку API разбирает числа JSON как числа двойной точности и иначе повреждал бы значения вне диапазона[-2^53 + 1, 2^53 - 1].
Примеры
gcloud:
Ограничения
- Можно читать только собственные таблицы BigQuery. Для представлений и внешних таблиц требуется запуск задания запроса BigQuery, чего эта функция не делает.
- Столбцы
RANGEможно читать (какString), но нельзя записывать в них: вставка в столбецRANGEвызывает ошибку. - Значение
GEOGRAPHY, представляющее собойGEOMETRYCOLLECTIONили пустую геометрию, невозможно представить типомGeometry, поэтому чтение строки с таким значением вызывает ошибку. Запись значенияGeometry, равногоNULL, в обязательное полеGEOGRAPHY(REQUIRED) или в качестве элемента повторяемого поляGEOGRAPHY(REPEATED) отклоняется, поскольку BigQuery не допускает тамNULL. - Предикаты не проталкиваются:
tabledata.listтолько перечисляет строки таблицы и не имеет параметра фильтрации (он принимает параметры пагинации, выбора столбцов и формата), а для фильтрации потребовался бы запуск задания запроса BigQuery, чего эта функция не делает. Поэтому условиеWHEREприменяется в ClickHouse после загрузки строк; используйте выбор столбцов, чтобы уменьшить объём передаваемых данных. LIMIT, напротив, уменьшает объём считываемых данных. Страницы запрашиваются по мере необходимости, при этомmaxResultsустанавливается вmax_block_size, а после получения запросом достаточного количества строк новые страницы не запрашиваются. Для простогоLIMIT n(безWHERE,GROUP BY,ORDER BYи приnменьшеmax_block_size) ClickHouse уменьшаетmax_block_sizeдоn, поэтому выполняется ровно один запрос ровно наnстрок; в противном случае чтение останавливается на первой границе страницы после лимита, превышая его менее чем на одну страницу.- Чтение привязывается к схеме, видимой на этапе анализа запроса, путём передачи явного списка столбцов в
tabledata.list. Для очень широкого чтения, при котором список столбцов превышает ограничение на длину URL запроса (например,SELECT *из таблицы с тысячами столбцов), запрос отклоняется, а не выполняется без такой привязки (чтение без привязки может быть нарушено одновременным изменением схемы); выберите меньше столбцов, чтобы список поместился. То же ограничение длины URL проверяется перед каждым постраничным запросом (каждая страница содержит непрозрачныйpageToken), поэтому чтение, для которого последующие страницы не помещаются в это ограничение, отклоняется с той же ошибкой вместо сбоя в середине выполнения. - Если таблица BigQuery изменена после чтения её схемы, запрос отклоняется вместо того, чтобы незаметно вернуть или записать несоответствующие данные: актуальная схема повторно запрашивается и сравнивается со схемой, использованной при анализе, непосредственно перед чтением, а также перед тем, как
INSERTпередаст первую строку. Оставшееся окно (изменение схемы между этой проверкой и следующими за ней запросами) нельзя устранить, поскольку схема и данные запрашиваются отдельными REST-запросами. - Сравнение выполняется со снимком схемы, использованным при анализе запроса: он создаётся, когда табличная функция определяет свою структуру, или, для постоянной таблицы (таблицы с движком
BigQueryлибо таблицы, созданной с помощьюCREATE TABLE ... AS bigquery(...), которая аналогично сохраняет свои столбцы), при первом чтении или записи послеCREATE,ATTACHлибо перезапуска сервера. В метаданных таблицы сохраняются сопоставленные столбцы ClickHouse, а не схема BigQuery, поэтому изменение схемы, выполненное, пока таблица была отсоединена (или сервер был выключен), принимается следующим запросом, а не отклоняется: объявленные столбцы по-прежнему проверяются по актуальной схеме, а строки декодируются с её помощью, поэтому изменение, сохраняющее сопоставленные типы ClickHouse (например, сSTRINGнаBYTES), читается по правилам нового типа при том же типе столбца. - Строки, записанные потоковыми вставками, попадают в потоковый буфер BigQuery и могут появиться в последующих чтениях не сразу.
- Большой
INSERTотправляется вtabledata.insertAllпакетами: не более 500 строк в запросе; кроме того, данные разбиваются так, чтобы каждый запрос не превышал ограничение BigQuery на размер запроса в 10 МБ (одна строка, превышающая это ограничение, отклоняется с понятной ошибкой). - Операции записи не являются атомарными, и отдельный запрос
tabledata.insertAllможет выполниться лишь частично: BigQuery может зафиксировать часть строк запроса, отклонив остальные сinsertErrors. Запросы также фиксируются независимо друг от друга, поэтому более поздний батч может быть отклонён уже после принятия предыдущих. В обоих случаях запрос возвращает ошибку, но уже зафиксированные строки остаются в BigQuery. Чтобы ограничить дублирование, каждая строка отправляется со стабильнымinsertId, сформированным из идентификатора запроса и порядкового номера строки в потоке; BigQuery использует его для дедупликации по мере возможности в пределах окна потоковой вставки.query_id, превышающий ограничение BigQuery в 128 символов дляinsertId, хешируется в префикс фиксированной длины, который остаётся стабильным для данногоquery_id. ПосколькуinsertIdзависит от порядкового номера, дедупликация надёжна только при повторном запуске, возвращающем строки в том же порядке: повторная попытка передачи батча всегда безопасна, а повторный запуск того жеINSERTс тем жеquery_idобеспечивает дедупликацию только при передаче строк в том же порядке (например, при однопоточной вставке или при ином детерминированном порядке — задайтеmax_threads = 1иmax_insert_threads = 1для параллельногоINSERT ... SELECT, порядок фрагментов которого иначе может меняться между попытками).