ClickHouse Go
Скопируйте код примера
Скопируйте этот код в каталог clickhouse-golang-example
под именем main.go
.
Выполните go mod tidy
Установите данные для подключения
Ранее вы искали свои данные для подключения. Установите их в main.go
в функции connect()
:
Запустите пример
Узнайте больше
Остальная часть документации в этой категории охватывает детали клиента ClickHouse Go.
Клиент ClickHouse Go
ClickHouse поддерживает два официальных клиента Go. Эти клиенты дополняют друг друга и намеренно поддерживают разные сценарии использования.
- clickhouse-go - Клиент высокого уровня, который поддерживает как стандартный интерфейс базы данных sql для Go, так и нативный интерфейс.
- ch-go - Клиент низкого уровня. Только нативный интерфейс.
clickhouse-go предоставляет интерфейс высокого уровня, позволяя пользователям выполнять запросы и вставлять данные, используя ориентированную на строки семантику и пакетную обработку, которые допускают дочерние типы данных - значения будут преобразованы, при условии, что не будет потенциальных потерь точности. ch-go, в свою очередь, предоставляет оптимизированный ориентированный на столбцы интерфейс, который обеспечивает быструю потоковую передачу блоков данных с низкими затратами по CPU и памяти за счет строгости типов и более сложного использования.
Начиная с версии 2.3, Clickhouse-go использует ch-go для низкоуровневых функций, таких как кодирование, декодирование и сжатие. Обратите внимание, что clickhouse-go также поддерживает стандартный интерфейс Go database/sql
. Оба клиента используют нативный формат для своего кодирования, чтобы обеспечить оптимальную производительность и могут связываться через нативный протокол ClickHouse. Также clickhouse-go поддерживает HTTP как механизм передачи для случаев, когда пользователи имеют необходимость в проксировании или балансировке нагрузки.
При выборе библиотеки клиента пользователи должны быть осведомлены о их соответствующих преимуществах и недостатках - смотрите Выбор библиотеки клиента.
Нативный формат | Нативный протокол | HTTP протокол | API для ориентированных на строки | API для ориентированных на столбцы | Гибкость типов | Сжатие | Заполнители запросов | |
---|---|---|---|---|---|---|---|---|
clickhouse-go | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
ch-go | ✅ | ✅ | ✅ | ✅ |
Выбор клиента
Выбор библиотеки клиента зависит от ваших паттернов использования и необходимости в оптимальной производительности. Для сценариев с частыми вставками, где требуется миллионы вставок в секунду, мы рекомендуем использовать низкоуровневый клиент ch-go. Этот клиент избегает связанных накладных расходов по преобразованию данных из формата, ориентированного на строки, в столбцы, как требует нативный формат ClickHouse. Более того, он избегает всякого отражения или использования типа interface{}
(any
), чтобы упростить использование.
Для нагрузок запросов, сосредоточенных на агрегациях или более низких нагрузках вставки, clickhouse-go предоставляет знакомый интерфейс database/sql
и более простую семантику строк. Пользователи также могут по желанию использовать HTTP для протокола передачи и воспользоваться вспомогательными функциями для преобразования строк в структуры и наоборот.
Клиент clickhouse-go
Клиент clickhouse-go предоставляет два API-интерфейса для взаимодействия с ClickHouse:
- Специфический API клиента ClickHouse
- Стандартный
database/sql
- общий интерфейс для SQL баз данных, предоставляемых Golang.
Хотя database/sql
предоставляет базу независимо от клиента, позволяя разработчикам абстрагировать свое хранилище данных, он накладывает некоторые ограничения на типизацию и семантику запросов, которые влияют на производительность. По этой причине необходимо использовать API, специфичный для клиента, в тех случаях, когда производительность важна. Тем не менее пользователи, которые желают интегрировать ClickHouse в инструменты, поддерживающие несколько баз данных, могут предпочесть использовать стандартный интерфейс.
Оба интерфейса кодируют данные, используя нативный формат и нативный протокол для связи. Дополнительно стандартный интерфейс поддерживает связь по HTTP.
Нативный формат | Нативный протокол | HTTP протокол | Поддержка массовой записи | Сериализация структур | Сжатие | Заполнители запросов | |
---|---|---|---|---|---|---|---|
API ClickHouse | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
database/sql API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Установка
v1 драйвера устарел и не будет получать обновления по функциям или поддержку новых типов ClickHouse. Пользователи должны перейти на v2, который предлагает более высокую производительность.
Чтобы установить версию 2.x клиента, добавьте пакет в ваш файл go.mod:
require github.com/ClickHouse/clickhouse-go/v2 main
Или, склонируйте репозиторий:
Чтобы установить другую версию, измените путь или имя ветки соответственно.
Версии и совместимость
Клиент выпускается независимо от ClickHouse. 2.x представляет текущую основную версию в разработке. Все версии 2.x должны быть совместимы между собой.
Совместимость с ClickHouse
Клиент поддерживает:
- Все текущие поддерживаемые версии ClickHouse, указанные здесь. Поскольку версии ClickHouse больше не поддерживаются, они также больше не тестируются с выпусками клиента.
- Все версии ClickHouse в течение 2 лет с момента выпуска клиента. Обратите внимание, что только LTS версии активно тестируются.
Совместимость с Golang
Версия клиента | Версии Golang |
---|---|
=> 2.0 <= 2.2 | 1.17, 1.18 |
>= 2.3 | 1.18 |
API клиента ClickHouse
Все примеры кода для API клиента ClickHouse можно найти здесь.
Подключение
Следующий пример, который возвращает версию сервера, демонстрирует подключение к ClickHouse в предположении, что ClickHouse не защищен и доступен с использованием учетной записи по умолчанию.
Обратите внимание, что мы используем стандартный нативный порт для подключения.
Во всех последующих примерах, если это не указано явно, мы предполагаем, что используется переменная ClickHouse conn
, которая была создана и доступна.
Настройки подключения
При открытии соединения можно использовать структуру Options для управления поведением клиента. Доступны следующие настройки:
Protocol
- либо Нативный, либо HTTP. HTTP в настоящее время поддерживается только для API database/sql.TLS
- параметры TLS. Значение, отличное от nil, включает TLS. Смотрите Использование TLS.Addr
- срез адресов, включая порт.Auth
- Подробности аутентификации. Смотрите Аутентификация.DialContext
- пользовательская функция набора, чтобы определить, как устанавливаются соединения.Debug
- true/false для активации отладки.Debugf
- предоставляет функцию для получения отладочного вывода. Требует, чтобыdebug
был установлен в true.Settings
- карта настроек ClickHouse. Эти настройки будут применены ко всем запросам ClickHouse. Использование контекста позволяет установить настройки для каждого запроса.Compression
- включить сжатие для блоков. См. Сжатие.DialTimeout
- максимальное время для установления соединения. По умолчанию1s
.MaxOpenConns
- максимальное количество соединений для использования в любое время. Меньшее или большее количество соединений может находиться в неактивном пуле, но только это число может быть использовано в любое время. По умолчаниюMaxIdleConns+5
.MaxIdleConns
- количество соединений, которые должны поддерживаться в пуле. Соединения будут повторно использоваться, если это возможно. По умолчанию5
.ConnMaxLifetime
- максимальный срок службы, чтобы удерживать соединение доступным. По умолчанию 1 час. Соединения уничтожаются после этого времени, новые соединения добавляются в пул по мере необходимости.ConnOpenStrategy
- определяет, как должны использоваться и открываться адреса узлов. См. Подключение к нескольким узлам.BlockBufferSize
- максимальное количество блоков, которые могут быть декодированы в буфер за раз. Более крупные значения увеличат параллелизацию за счет использования памяти. Размеры блока зависят от запроса, поэтому, хотя вы можете установить это в соединении, мы рекомендуем переопределить его для каждого запроса в зависимости от возвращаемых данных. По умолчанию2
.
Пул соединений
Клиент поддерживает пул соединений, повторно используя их по запросам, как требуется. В любое время будет использоваться не более MaxOpenConns
, максимальный размер пула контролируется MaxIdleConns
. Клиент будет получать соединение из пула для каждого выполнения запроса, возвращая его в пул для повторного использования. Соединение используется на протяжении всего времени выполнения пакета и освобождается при Send()
.
Нет никаких гарантий, что то же самое соединение в пуле будет использоваться для последующих запросов, если пользователь не установит MaxOpenConns=1
. Это редко необходимо, но может потребоваться для случаев, когда пользователи используют временные таблицы.
Кроме того, обратите внимание, что по умолчанию ConnMaxLifetime
составляет 1 час. Это может привести к ситуациям, когда нагрузка на ClickHouse становится несбалансированной, если узлы покинут кластер. Это может произойти, когда узел становится недоступным, соединения будут балансироваться на другие узлы. Эти соединения будут существовать и не будут обновляться в течение 1 часа по умолчанию, даже если проблемный узел вернется в кластер. Рассмотрите возможность понижения этого значения в случаях высокой нагрузки.
Использование TLS
На низком уровне все методы подключения клиента (DSN/OpenDB/Open
) будут использовать пакет Go tls для установления защищенного соединения. Клиент знает использовать TLS, если структура Options содержит ненулевой указатель на tls.Config
.
Этот минимальный TLS.Config
обычно достаточно, чтобы подключиться к защищенному нативному порту (обычно 9440) на сервере ClickHouse. Если у сервера ClickHouse нет действительного сертификата (истек, неправильное имя хоста, не подписан публично признанным корневым удостоверяющим центром), InsecureSkipVerify
может быть истинным, но это настоятельно не рекомендуется.
Если дополнительные параметры TLS необходимы, код приложения должен установить желаемые поля в структуре tls.Config
. Это могут быть специфические шифры, принудительное использование определенной версии TLS (например, 1.2 или 1.3), добавление внутренней цепочки сертификатов CA, добавление клиентского сертификата (и закрытого ключа), если это требуется сервером ClickHouse, и большинство других параметров, которые предусмотрены более специализированной настройкой безопасности.
Аутентификация
Укажите структуру Auth в деталях подключения, чтобы указать имя пользователя и пароль.
Подключение к нескольким узлам
Несколько адресов могут быть указаны через структуру Addr
.
Доступны две стратегии подключения:
ConnOpenInOrder
(по умолчанию) - адреса обрабатываются по порядку. Поздние адреса используются только в случае неуспеха при подключении, используя адреса ранее в списке. Это фактически стратегия резервирования.ConnOpenRoundRobin
- Нагрузка распределяется по адресам с помощью стратегии кругового обхода.
Это можно контролировать с помощью параметра ConnOpenStrategy
.
Исполнение
Произвольные операторы могут выполняться через метод Exec
. Это полезно для DDL и простых операторов. Не следует использовать для крупных вставок или итераций запроса.
Обратите внимание на возможность передачи контекста в запрос. Это может быть использовано для передачи настроек конкретного уровня запроса - см. Использование контекста.
Пакетная вставка
Чтобы вставить большое количество строк, клиент предоставляет пакетные семантики. Это требует подготовки пакета, к которому могут быть добавлены строки. Он наконец отправляется через метод Send()
. Пакеты будут храниться в памяти до тех пор, пока не выполнится Send.
Рекомендации для ClickHouse применяются здесь. Пакеты не должны делиться между go-рутинами - создайте отдельный пакет для каждой рутины.
Из приведенного выше примера обратите внимание на необходимость согласования типов переменных с типами столбцов при добавлении строк. Хотя сопоставление обычно очевидно, этот интерфейс пытается быть гибким, и типы будут преобразованы, при условии, что не будет потерь точности. Например, приведенный ниже пример демонстрирует вставку строки в datetime64.
Для полного резюме поддерживаемых типов go для каждого типа столбца смотрите Преобразования типов.
Запрос строк/ов
Пользователи могут либо запрашивать одну строку, используя метод QueryRow
, либо получать курсор для итерации по наборам результатов через Query
. В то время как первый принимает назначение для данных, которые нужно сериализовать, последний требует вызова Scan
для каждой строки.
Обратите внимание, что в обоих случаях требуется передать указатель переменным, в которые мы хотим сериализовать соответствующие значения столбцов. Эти переменные должны быть переданы в том порядке, который указан в операторе SELECT
- по умолчанию будет использоваться порядок определения столбца в случае SELECT *
, как показано выше.
Аналогично вставке, метод Scan требует, чтобы целевые переменные соответствовали корректному типу. Это снова нацеливается на гибкость, с возможностью преобразования типов, при условии, что не будет потеряно точность, например, приведенный выше пример показывает, как столбец UUID считывается в переменную строки. Полный список поддерживаемых типов go для каждого типа столбца смотрите Преобразования типов.
Наконец, обратите внимание на возможность передачи Context
в методы Query
и QueryRow
. Это может быть использовано для настроек, специфичных для запросов - смотрите Использование контекста для получения дальнейших деталей.
Асинхронная вставка
Асинхронные вставки поддерживаются через метод Async. Это позволяет пользователю указать, должен ли клиент ждать, пока сервер завершит вставку, или ответить, как только данные будут приняты. Это эффективно контролирует параметр wait_for_async_insert.
Вставка в столбец
Записи можно вставить в столбцовом формате. Это может обеспечить преимущества производительности, если данные уже ориентированы в этой структуре, избегая необходимости поворачивать их в строки.
Использование структур
Для пользователей структуры Golang предоставляют логическое представление строки данных в ClickHouse. Чтобы помочь с этим, нативный интерфейс предоставляет несколько удобных функций.
Выбор с сериализацией
Метод Select позволяет выполнить маршалинг набора строк ответа в срез структур за одно обращение.
Сканирование структуры
ScanStruct
позволяет выполнить маршалинг одной строки из запроса в структуру.
Добавление структуры
AppendStruct
позволяет добавить структуру к существующему пакету и интерпретировать ее как полную строку. Это требует, чтобы столбцы структуры совпадали как по имени, так и по типу с таблицей. Хотя все столбцы должны иметь эквивалентное поле структуры, некоторые поля структуры могут не иметь эквивалентного представления в столбце. Эти поля просто будут проигнорированы.
Преобразования типов
Клиент стремится быть максимально гибким в отношении принятия переменных типов как для вставки, так и для маршалинга ответов. В большинстве случаев существует эквивалентный тип Golang для типа столбца ClickHouse, например, UInt64 к uint64. Эти логические соответствия всегда должны поддерживаться. Пользователи могут захотеть использовать переменные типы, которые могут быть вставлены в столбцы или использованы для получения ответа, если преобразование либо переменной, либо полученных данных происходит в первую очередь. Клиент стремится поддерживать эти преобразования прозрачно, чтобы пользователям не нужно было точно преобразовывать свои данные перед вставкой и обеспечивать гибкий маршалинг во время запроса. Это прозрачное преобразование не допускает потери точности. Например, uint32 не может быть использован для получения данных из столбца UInt64. Напротив, строка может быть вставлена в поле datetime64, при условии что она соответствует требованиям формата.
Преобразования типов, в настоящее время поддерживаемые для примитивных типов, зафиксированы здесь.
Эта работа продолжается и может быть разделена на вставку (Append
/AppendRow
) и время чтения (через Scan
). Если вам нужна поддержка конкретного преобразования, пожалуйста, создайте проблему.
Сложные типы
Типы Date/DateTime
Клиент Go ClickHouse поддерживает типы Date
, Date32
, DateTime
и DateTime64
. Даты могут быть вставлены как строка в формате 2006-01-02
или с использованием родного go time.Time{}
или sql.NullTime
. Дата и Время также поддерживают последние типы, но требуют, чтобы строки передавались в формате 2006-01-02 15:04:05
с необязательным смещением часового пояса, например, 2006-01-02 15:04:05 +08:00
. time.Time{}
и sql.NullTime
поддерживаются как во время чтения, так и любая реализация интерфейса sql.Scanner
.
Обработка информации о часовом поясе зависит от типа ClickHouse и от того, вставляется ли значение или читается:
- DateTime/DateTime64
- В время вставки значение отправляется в ClickHouse в формате метки времени UNIX. Если часовой пояс не указан, клиент будет предполагать местный часовой пояс клиента.
time.Time{}
илиsql.NullTime
будет преобразован в эпоху соответственно. - В время выбора будет использоваться часовой пояс стобца, если установлен, при возврате значения
time.Time
. Если нет, будет использоваться часовой пояс сервера.
- В время вставки значение отправляется в ClickHouse в формате метки времени UNIX. Если часовой пояс не указан, клиент будет предполагать местный часовой пояс клиента.
- Date/Date32
- В время вставки часовой пояс любой даты учитывается при преобразовании даты в метку времени UNIX, т.е. он будет сдвинут по часовому поясу перед хранением в качестве даты, поскольку типы Date имеют локаль в ClickHouse. Если это не указано в строковом значении, будет использован местный часовой пояс.
- В время выбора даты считываются в
time.Time{}
илиsql.NullTime{}
экземпляры и возвращаются без информации о часовом поясе.
Массив
Массивы должны быть вставлены как срезы. Правила типизации для элементов согласуются с правилами для примитивного типа, т.е. где это возможно, элементы будут преобразованы.
Указатель на срез должен быть предоставлен во время Scanning.
Словарь
Словари должны быть вставлены как карты Golang с ключами и значениями, соответствующими правилам типов, определенным ранее.
Кортежи
Кортежи представляют собой группу колонок произвольной длины. Столбцы могут быть либо явно названы, либо просто указывать тип, например:
Из этих подходов именованные кортежи предлагают большую гибкость. В то время как безымянные кортежи должны быть вставлены и прочитаны с использованием срезов, именованные кортежи также совместимы с картами.
Примечание: поддерживаются типизированные срезы и карты, при условии что подстолбцы в именованном кортеже имеют один и тот же тип.
Вложенные
Вложенное поле эквивалентно массиву именованных кортежей. Использование зависит от того, установил ли пользователь flatten_nested в 1 или 0.
Установив flatten_nested в 0, вложенные столбцы остаются в качестве одного массива кортежей. Это позволяет пользователям использовать срезы карт для вставки и извлечения, а также произвольные уровни вложенности. Ключ карты должен равняться имени столбца, как показано в примере ниже.
Примечание: поскольку карты представляют собой кортеж, они должны быть типа map[string]interface{}
. Значения в настоящее время не имеют строгой типизации.
Полный пример - flatten_tested=0
Если используется значение по умолчанию 1 для flatten_nested
, вложенные столбцы упрощаются до отдельных массивов. Это требует использования вложенных срезов для вставки и извлечения. Хотя произвольные уровни вложенности могут работать, это не является официально поддерживаемым.
Полный пример - flatten_nested=1
Примечание: Вложенные столбцы должны иметь одинаковые размеры. Например, в приведенном выше примере Col2_2
и Col2_1
должны иметь одинаковое количество элементов.
Из-за более простого интерфейса и официальной поддержки вложенности, мы рекомендуем flatten_nested=0
.
Гео типы
Клиент поддерживает гео типы Point, Ring, Polygon и Multi Polygon. Эти поля находятся в Golang с использованием пакета github.com/paulmach/orb.
UUID
Тип UUID поддерживается пакетом github.com/google/uuid. Пользователи также могут отправлять и маршалить UUID как строку или любой тип, который реализует sql.Scanner
или Stringify
.
Десятичные числа
Тип Decimal поддерживается пакетом github.com/shopspring/decimal.
Nullable
go значение Nil представляет ClickHouse NULL. Это может быть использовано, если поле объявлено как Nullable. Во время вставки Nil может быть передан как для обычной, так и для Nullable версии столбца. Для первой будет сохранено значение по умолчанию для типа, т.е. пустая строка для строки. Для nullable версии в ClickHouse будет сохранено значение NULL.
Во время сканирования пользователь должен передать указатель на тип, который поддерживает nil, т.е. *string, чтобы представить значение nil для поля Nullable. В примере ниже col1, который является Nullable(String), таким образом получает string. Это позволяет представить nil.
Клиент также поддерживает типы sql.Null*
, например, sql.NullInt64
. Они совместимы с их эквивалентными типами ClickHouse.
Большие числа - Int128, Int256, UInt128, UInt256
Числовые типы больше 64 бит представлены с использованием родного go big пакета.
Сжатие
Поддержка методов сжатия зависит от используемого подлежащего протокола. Для родного протокола клиент поддерживает LZ4
и ZSTD
сжатие. Это выполняется только на уровне блока. Сжатие может быть включено путем включения конфигурации Compression
с подключением.
Дополнительные методы сжатия доступны, если использовать стандартный интерфейс через HTTP. См. API database/sql - Сжатие для более подробной информации.
Привязка параметров
Клиент поддерживает привязку параметров для методов Exec
, Query
и QueryRow
. Как показано в примере ниже, это поддерживается с использованием именованных, нумерованных и позиционных параметров. Мы предоставляем примеры этих ниже.
Специальные случаи
По умолчанию, срезы будут развернуты в список значений, разделенных запятой, если переданы в качестве параметра к запросу. Если пользователям требуется набор значений, которые должны быть внедрены с оберткой [ ]
, следует использовать ArraySet
.
Если требуются группы/кортежи с оберткой ( )
, например, для использования с операторами IN, пользователи могут использовать GroupSet
. Это особенно полезно для случаев, когда требуются несколько групп, как показано в примере ниже.
Наконец, поля DateTime64 требуют точности для того, чтобы гарантировать, что параметры отображаются правильно. Уровень точности для поля неизвестен клиенту, поэтому пользователь должен предоставить его. Для этого мы предлагаем параметр DateNamed
.
Использование Контекста
Контексты Go предоставляют способ передачи сроков, сигналов отмены и других значений, зависящих от запроса, через границы API. Все методы подключения принимают контекст в качестве первой переменной. В то время как предыдущие примеры использовали context.Background(), пользователи могут использовать эту возможность для передачи настроек и сроков, а также для отмены запросов.
Передача контекста, созданного с помощью withDeadline
, позволяет устанавливать временные ограничения на выполнение запросов. Обратите внимание, что это абсолютное время, и истечение срока только освободит соединение и отправит сигнал отмены в ClickHouse. В качестве альтернативы можно использовать WithCancel
для явной отмены запроса.
Помощники clickhouse.WithQueryID
и clickhouse.WithQuotaKey
позволяют задать идентификатор запроса и ключ квоты. Идентификаторы запросов могут быть полезны для отслеживания запросов в журналах и в целях отмены. Ключ квоты можно использовать для наложения ограничений на использование ClickHouse на основе уникального значения ключа - см. Управление квотами для получения дополнительной информации.
Пользователи также могут использовать контекст, чтобы гарантировать, что настройка применяется только для конкретного запроса, а не для всего соединения, как показано в Настройки соединения.
Наконец, пользователи могут контролировать размер буфера блоков с помощью clickhouse.WithBlockSize
. Это переопределяет настройку уровня соединения BlockBufferSize
и контролирует максимальное количество блоков, которые декодируются и хранятся в памяти в любой момент времени. Более крупные значения могут означать большее параллелизм за счет использования памяти.
Примеры выше показаны ниже.
Прогресс/Профиль/Информация о журнале
Прогресс, профиль и информация о журнале могут запрашиваться по запросам. Информация о прогрессе будет сообщать статистику по количеству строк и байтов, которые были прочитаны и обработаны в ClickHouse. Напротив, информация о профиле предоставляет сводку данных, возвращенных клиенту, включая итоги байтов (не сжатых), строк и блоков. Наконец, информация о журнале предоставляет статистику по потокам, например, использование памяти и скорость передачи данных.
Об получение этой информации требуется, чтобы пользователь использовал Контекст, в который пользователь может передать функции обратного вызова.
Динамическое сканирование
Пользователям может потребоваться читать таблицы, схема или тип полей которых им неизвестны. Это часто встречается в случаях, когда выполняется спонтанный анализ данных или пишутся универсальные инструменты. Для достижения этого информация о типе столбца доступна в ответах на запросы. Это можно использовать с помощью рефлексии Go для создания экземпляров корректных по типу переменных, которые могут быть переданы в Scan.
Внешние таблицы
Внешние таблицы позволяют клиенту отправлять данные в ClickHouse с помощью запроса SELECT. Эти данные помещаются во временную таблицу и могут быть использованы в самом запросе для оценки.
Чтобы отправить внешние данные клиенту с помощью запроса, пользователю необходимо создать внешнюю таблицу через ext.NewTable
перед передачей этого через контекст.
Open Telemetry
ClickHouse позволяет передавать контекст трассировки как часть нативного протокола. Клиент позволяет создать Span с помощью функции clickhouse.withSpan
и передать его через контекст для достижения этого.
Полную информацию о трассировке можно найти в разделе Поддержка OpenTelemetry.
Database/SQL API
database/sql
или "стандартный" API позволяет пользователям использовать клиент в сценариях, где код приложения должен быть независимым от баз данных, предоставляя стандартный интерфейс. Это имеет свои затраты - дополнительные уровни абстракции и индирекции, а также примитивы, которые не обязательно совпадают с ClickHouse. Тем не менее, эти затраты обычно приемлемы в сценариях, когда инструменты должны подключаться к нескольким базам данных.
Кроме того, этот клиент поддерживает использование HTTP в качестве транспортного уровня - данные по-прежнему будут закодированы в нативном формате для оптимальной производительности.
Следующее стремится отразить структуру документации для API ClickHouse.
Полные примеры кода для стандартного API можно найти здесь.
Подключение
Соединение можно осуществить либо через строку DSN формата clickhouse://<host>:<port>?<query_option>=<value>
и метод Open
, либо через метод clickhouse.OpenDB
. Последний не является частью спецификации database/sql
, но возвращает экземпляр sql.DB
. Этот метод предоставляет функциональность, такую как профилирование, для которой нет очевидных способов раскрытия через спецификацию database/sql
.
Для всех последующих примеров, если не указано иное, мы предполагаем, что используется переменная ClickHouse conn
, которая была создана и доступна.
Настройки соединения
Следующие параметры могут быть переданы в строку DSN:
hosts
- список хостов с одним адресом, разделенных запятыми, для балансировки нагрузки и отказоустойчивости - см. Подключение к нескольким узлам.username/password
- учетные данные аутентификации - см. Аутентификацияdatabase
- выбрать текущую базу данных по умолчаниюdial_timeout
- строка длительности, представляющая собой возможно подписанную последовательность десятичных чисел, каждое с необязательной дробной частью и суффиксом единицы, таким как300ms
,1s
. Допустимые единицы времени:ms
,s
,m
.connection_open_strategy
-random/in_order
(по умолчаниюrandom
) - см. Подключение к нескольким узламround_robin
- выбрать сервер по кругу из набораin_order
- первый доступный сервер выбирается в указанном порядке
debug
- включить отладочный вывод (булевое значение)compress
- указать алгоритм сжатия -none
(по умолчанию),zstd
,lz4
,gzip
,deflate
,br
. Если установлено вtrue
, будет использоватьсяlz4
. Толькоlz4
иzstd
поддерживаются для нативной коммуникации.compress_level
- уровень сжатия (по умолчанию0
). См. Сжатие. Это специфично для алгоритма:gzip
--2
(Лучшая скорость) до9
(Лучшее сжатие)deflate
--2
(Лучшая скорость) до9
(Лучшее сжатие)br
-0
(Лучшая скорость) до11
(Лучшее сжатие)zstd
,lz4
- игнорируется
secure
- установить безопасное SSL-соединение (по умолчаниюfalse
)skip_verify
- пропустить проверку сертификата (по умолчаниюfalse
)block_buffer_size
- позволяет пользователям контролировать размер буфера блоков. См.BlockBufferSize
. (по умолчанию2
)
Пул соединений
Пользователи могут влиять на использование предоставленного списка адресов узлов, как описано в Подключение к нескольким узлам. Однако управление и пуллирование соединений делегируется sql.DB
по замыслу.
Подключение по HTTP
По умолчанию соединения устанавливаются через нативный протокол. Для пользователей, нуждающихся в HTTP, это можно включить, либо изменив строку DSN, чтобы включить HTTP-протокол, либо указав Протокол в параметрах подключения.
Подключение к нескольким узлам
Если использовать OpenDB
, подключитесь к нескольким хостам, используя тот же подход с параметрами, как это делается для API ClickHouse - дополнительно указав ConnOpenStrategy
.
Для соединений на основе DSN строка принимает несколько хостов и параметр connection_open_strategy
, для которого можно установить значение round_robin
или in_order
.
Использование TLS
Если использовать строку подключения DSN, SSL можно включить с помощью параметра "secure=true". Метод OpenDB
использует тот же подход, что и глобальный API для TLS, полагаясь на указание ненулевой структуры TLS. Хотя строка подключения DSN поддерживает параметр skip_verify для пропуска проверки SSL, метод OpenDB
требуется для более сложных конфигураций TLS - так как он позволяет передавать конфигурацию.
Аутентификация
Если использовать OpenDB
, информацию об аутентификации можно передать через обычные параметры. Для соединений на основе DSN имя пользователя и пароль могут быть переданы в строке подключения - либо в качестве параметров, либо как учетные данные, закодированные в адресе.
Выполнение
После получения соединения пользователи могут выдавать SQL-запросы для выполнения через метод Exec.
Этот метод не поддерживает получение контекста - по умолчанию он выполняется с фоновым контекстом. Пользователи могут использовать ExecContext
, если это необходимо - см. Использование контекста.
Пакетная вставка
Пакетная семантика может быть достигнута путем создания sql.Tx
с помощью метода Begin
. Отсюда пакет можно получить с помощью метода Prepare
с оператором INSERT
. Это возвращает sql.Stmt
, к которому строки могут быть добавлены с использованием метода Exec
. Пакет будет накапливаться в памяти до тех пор, пока не будет выполнен Commit
в исходном sql.Tx
.
Запрос строк
Запрос одной строки можно осуществить с помощью метода QueryRow
. Это возвращает *sql.Row
, на котором можно вызвать Scan с указателями на переменные, в которые должны быть преобразованы столбцы. Вариант QueryRowContext
позволяет передавать контекст, отличный от фонового - см. Использование контекста.
Итерация по нескольким строкам требует метода Query
. Это возвращает структуру *sql.Rows
, на которой можно вызвать Next, чтобы пройти через строки. Эквивалент QueryContext
позволяет передавать контекст.
Асинхронная вставка
Асинхронные вставки можно осуществить, выполняя вставку с помощью метода ExecContext
. Этот метод должен получать контекст с включенным асинхронным режимом, как показано ниже. Это позволяет пользователю указать, должен ли клиент ожидать завершения сервера после вставки или отвечать, как только данные будут получены. Это эффективно контролирует параметр wait_for_async_insert.
Столбцовая вставка
Не поддерживается при использовании стандартного интерфейса.
Использование структур
Не поддерживается при использовании стандартного интерфейса.
Преобразования типов
Стандартный интерфейс database/sql
должен поддерживать те же типы, что и API ClickHouse. Есть несколько исключений, в основном для сложных типов, которые мы документируем ниже. Подобно API ClickHouse, клиент направлен на максимальную гибкость в отношении принятия переменных типов как для вставки, так и для преобразования ответов. См. Преобразования типов для получения дополнительной информации.
Сложные типы
Если не указано иное, работа со сложными типами должна быть такой же, как и в API ClickHouse. Различия являются результатом внутренних процессов database/sql
.
Карты
В отличие от API ClickHouse, стандартному API требуется, чтобы карты были сильно типизированы при типе сканирования. Например, пользователи не могут передавать map[string]interface{}
для поля Map(String,String)
и должны использовать map[string]string
вместо этого. Переменная interface{}
всегда будет совместима и может использоваться для более сложных структур. Структуры не поддерживаются во время чтения.
Поведение вставки такое же, как в API ClickHouse.
Сжатие
Стандартный API поддерживает те же алгоритмы сжатия, что и родной ClickHouse API, т.е. сжатие lz4
и zstd
на уровне блока. В дополнение поддерживается сжатие gzip, deflate и br для HTTP-соединений. Если любой из этих параметров включен, сжатие выполняется на блоках во время вставки и для ответов на запросы. Другие запросы, например, пинги или запросы, останутся несжатыми. Это соответствует параметрам lz4
и zstd
.
Если используется метод OpenDB
для установления соединения, можно передать конфигурацию Compression. Это включает возможность указать уровень сжатия (см. ниже). Если подключение осуществляется через sql.Open
с DSN, используйте параметр compress
. Это может быть либо конкретный алгоритм сжатия, т.е. gzip
, deflate
, br
, zstd
или lz4
, либо логический флаг. Если установлен в true, будет использоваться lz4
. По умолчанию none
, т.е. сжатие отключено.
Уровень применяемого сжатия можно контролировать с помощью параметра DSN compress_level
или поля Level
опции Compression
. По умолчанию 0, но он специфичен для алгоритма:
gzip
--2
(Лучшая скорость) до9
(Лучшее сжатие)deflate
--2
(Лучшая скорость) до9
(Лучшее сжатие)br
-0
(Лучшая скорость) до11
(Лучшее сжатие)zstd
,lz4
- игнорируются
Привязка параметров
Стандартный API поддерживает те же возможности привязки параметров, что и ClickHouse API, позволяя передавать параметры в методы Exec
, Query
и QueryRow
(и их эквиваленты Context). Поддерживаются позиционные, именованные и нумерованные параметры.
Обратите внимание, что особые случаи по-прежнему применяются.
Использование контекста
Стандартный API поддерживает такую же возможность передачи крайних сроков, сигналов отмены и других значений, связанных с запросом, через контекст, как и ClickHouse API. В отличие от ClickHouse API, это достигается путем использования вариантов методов Context
, т.е. методов, таких как Exec
, которые по умолчанию используют фоновый контекст, имеют вариант ExecContext
, в который можно передать контекст в качестве первого параметра. Это позволяет передавать контекст на любом этапе потока приложения. Например, пользователи могут передать контекст при установлении соединения через ConnContext
или при запросе строки через QueryRowContext
. Примеры всех доступных методов показаны ниже.
Для получения более подробной информации о том, как использовать контекст для передачи крайних сроков, сигналов отмены, идентификаторов запросов, ключей квоты и параметров соединения, смотрите раздел "Использование контекста" для ClickHouse API.
Сессии
В то время как родные соединения по своей природе имеют сессию, соединения через HTTP требуют от пользователя создания идентификатора сессии для передачи в контексте как параметра. Это позволяет использовать функции, например, временные таблицы, которые связаны с сессией.
Динамическое сканирование
Аналогично ClickHouse API, информация о типах столбцов доступна, что позволяет пользователям создавать экземпляры правильно типизированных переменных во время выполнения, которые можно передавать в функцию Scan. Это позволяет считывать столбцы, для которых тип не известен.
Внешние таблицы
Внешние таблицы позволяют клиенту отправлять данные в ClickHouse с помощью запроса SELECT
. Эти данные помещаются во временную таблицу и могут быть использованы в самом запросе для оценки.
Чтобы отправить внешние данные клиенту с помощью запроса, пользователь должен создать внешнюю таблицу через ext.NewTable
, прежде чем передать это через контекст.
Open Telemetry
ClickHouse позволяет передавать контекст трассировки в качестве части родного протокола. Клиент позволяет создать Span с помощью функции clickhouse.withSpan
и передать его через Context для достижения этого. Это не поддерживается при использовании HTTP в качестве транспортного средства.
Рекомендации по производительности
- Используйте ClickHouse API, где это возможно, особенно для примитивных типов. Это избегает значительного отражения и косвенных ссылок.
- Если вы читаете большие наборы данных, подумайте о модификации
BlockBufferSize
. Это увеличит использование памяти, но позволит декодировать больше блоков параллельно во время итерации строк. Значение по умолчанию 2 является консервативным и минимизирует накладные расходы по памяти. Более высокие значения будут означать больше блоков в памяти. Это требует тестирования, поскольку разные запросы могут производить разные размеры блоков. Это также можно установить на уровне запроса через контекст. - Будьте специфичными с вашими типами при вставке данных. Хотя клиент стремится быть гибким, например, позволяет распознавать строки для UUID или IP, это требует проверки данных и влечет за собой затраты на время вставки.
- Используйте вставки с ориентацией на столбцы, где это возможно. Снова эти вставки должны быть строго типизированы, избегая необходимости конвертировать ваши значения.
- Следуйте рекомендациям ClickHouse для оптимальной производительности вставки.