ClickHouse Go
Скопируйте пример кода
Скопируйте этот код в директорию clickhouse-golang-example
под именем main.go
.
Запустите go mod tidy
Установите ваши данные для подключения
Ранее вы узнали ваши данные для подключения. Установите их в main.go
в функции connect()
:
Запустите пример
Узнать больше
Остальная часть документации в этой категории охватывает детали клиента ClickHouse Go.
Клиент ClickHouse Go
ClickHouse поддерживает два официальных Go-клиента. Эти клиенты дополняют друг друга и целенаправленно поддерживают различные сценарии использования.
- clickhouse-go - клиент высокого уровня, который поддерживает либо стандартный интерфейс database/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:
- Специфический для клиента ClickHouse API
- Стандартный
database/sql
- общий интерфейс для SQL баз данных, предоставленный Golang.
Хотя database/sql
предоставляет абстрактный интерфейс для баз данных, позволяя разработчикам абстрагировать свое хранилище данных, он налагает некоторые типы и семантику запросов, которые влияют на производительность. По этой причине специфический для клиента API должен использоваться, когда производительность важна. Однако пользователи, которые хотят интегрировать ClickHouse в инструменты, поддерживающие несколько баз данных, могут предпочесть стандартный интерфейс.
Оба интерфейса кодируют данные, используя нативный формат и нативный протокол для общения. Кроме того, стандартный интерфейс поддерживает связь по HTTP.
Нативный формат | Нативный протокол | HTTP протокол | Поддержка массовой записи | Маршалинг структур | Сжатие | Заполнители запросов | |
---|---|---|---|---|---|---|---|
ClickHouse API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
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 не защищен и доступен с помощью пользователя по умолчанию.
Обратите внимание, что мы используем стандартный нативный порт для подключения.
Для всех последующих примеров, если не указано иное, мы предполагаем, что переменная conn
ClickHouse была создана и доступна.
Настройки соединения
При открытии соединения можно использовать структуру Options для управления поведением клиента. Доступны следующие настройки:
Protocol
- либо Нативный, либо HTTP. HTTP в настоящее время поддерживается только для API database/sql.TLS
- параметры TLS. Ненулевое значение включает 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
может быть установлено в true, но это строго не рекомендуется.
Если необходимы дополнительные параметры TLS, код приложения должен установить необходимые поля в структуре tls.Config
. Это может включать конкретные шифры, принуждение к определенной версии TLS (например, 1.2 или 1.3), добавление внутренней цепочки сертификатов CA, добавление клиентского сертификата (и закрытого ключа), если это требуется сервером ClickHouse, и большинство других параметров, которые приходят с более специализированной конфигурацией безопасности.
Аутентификация
Укажите структуру Auth в данных подключения, чтобы указать имя пользователя и пароль.
Подключение к нескольким узлам
Несколько адресов могут быть указаны через структуру Addr
.
Доступны две стратегии подключения:
ConnOpenInOrder
(по умолчанию) - адреса потребляются по порядку. Поздние адреса используются только в случае неудачи подключения с адресами, указанными ранее в списке. Это фактически стратегия переключения на резервный узел.ConnOpenRoundRobin
- Нагрузки балансируются по адресам с использованием стратегии кругового обхода.
Это можно контролировать через параметр ConnOpenStrategy
Выполнение
Произвольные операторы могут быть выполнены с помощью метода Exec
. Это полезно для DDL и простых операторов. Его не следует использовать для более крупных вставок или итераций запросов.
Обратите внимание на возможность передать контекст в запрос. Это может быть использовано для передачи конкретных настроек уровня запросов - см. Использование контекста.
Пакетная вставка
Чтобы вставить большое количество строк, клиент предоставляет семантику пакетной вставки. Это требует подготовки пакета, в который могут добавляться строки. Этот пакет отправляется через метод Send()
. Пакеты будут храниться в памяти до выполнения Send.
Рекомендации для ClickHouse применимы здесь. Пакеты не должны использоваться в нескольких горутинах - создавайте отдельный пакет для каждой рутины.
Из приведенного выше примера обратите внимание на необходимость согласования типов переменных с типом колонки при добавлении строк. Хотя отображение зачастую очевидно, этот интерфейс старается быть гибким, и типы будут конвертироваться, если не произойдет потеря точности. Например, следующий пример демонстрирует вставку строки в datetime64.
Для полного резюме поддерживаемых типов Go для каждого типа колонки см. Преобразование типов.
Запрос строк
Пользователи могут либо запрашивать одну строку с помощью метода QueryRow
, либо получить курсор для итерации по множеству результатов через Query
. В то время как первый принимает место назначения для сериализации данных, последний требует вызова Scan
для каждой строки.
Обратите внимание, что в обоих случаях мы должны передать указатель на переменные, в которые мы хотим сериализовать соответствующие значения колонок. Эти переменные должны передаваться в порядке, указанном в операторе SELECT
- по умолчанию будет использоваться порядок объявления колонок в случае SELECT *
, как показано выше.
Подобно вставкам, метод Scan требует, чтобы целевые переменные были соответствующего типа. Это снова призвано быть гибким, при этом типы конвертируются, где это возможно, при условии, что не возникнет потеря точности, например, в приведенном выше примере столбец UUID считывается в переменную строки. Для полного списка поддерживаемых типов Go для каждого типа колонки смотрите Преобразование типов.
Наконец, обратите внимание на возможность передать Context
в методы Query
и QueryRow
. Это можно использовать для настроек уровня запроса - смотрите Использование контекста для получения дополнительной информации.
Асинхронная вставка
Асинхронные вставки поддерживаются через метод Async. Это позволяет пользователю указать, должен ли клиент подождать, пока сервер завершит вставку, или ответить, как только данные будут получены. Это эффективно контролирует параметр wait_for_async_insert.
Вставка по колоннам
Вставки могут выполняться в колонном формате. Это может обеспечить преимущества по производительности, если данные уже ориентированы в этой структуре, избегая необходимости преобразовывать строки.
Использование структур
Для пользователей структуры Golang предоставляют логическое представление строки данных в ClickHouse. Для помощи в этом нативный интерфейс предоставляет несколько удобных функций.
Сканирование структуры
ScanStruct
позволяет сериализовать одну строку из запроса в структуру.
Добавление структуры
AppendStruct
позволяет добавить структуру к существующему пакету и интерпретировать её как полную строку. Это требует, чтобы колонки структуры соответствовали по имени и типу таблице. Хотя все колонки должны иметь эквивалентное поле структуры, некоторые поля структуры могут не иметь эквивалентного представления колонки. Эти поля просто будут игнорироваться.
Преобразования типов
Клиент стремится быть как можно более гибким в отношении приемлемых переменных типов как для вставки, так и для сериализации ответов. В большинстве случаев существует эквивалентный тип Golang для типа колонки ClickHouse, например, UInt64 соответствует uint64. Эти логические соответствия всегда должны поддерживаться. Пользователи могут захотеть использовать переменные типы, которые могут быть вставлены в колонки или использованы для получения ответа, если преобразование либо переменной, либо полученных данных происходит первым. Клиент стремится поддерживать эти преобразования прозрачно, чтобы пользователям не нужно было точно преобразовывать свои данные перед вставкой и обеспечивать гибкую сериализацию во время запроса. Это прозрачное преобразование не допускает потерь точности. Например, uint32 не может быть использован для получения данных из колонки UInt64. С другой стороны, строка может быть вставлена в поле datetime64, если она соответствует требованиям формата.
Преобразования типов, в настоящее время поддерживаемые для примитивных типов, собраны здесь.
Эта работа продолжается и может быть разделена на вставку (Append
/AppendRow
) и чтение (через Scan
). Если вам нужно поддержка для конкретного преобразования, пожалуйста, сообщите об этом.
Комплексные типы
Типы Дата/ДатаВремя
Клиент 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 и от того, вставляется значение или читается:
- ДатаВремя/ДатаВремя64
- При вставке значение отправляется в ClickHouse в формате UNIX timestamp. Если часовой пояс не указан, клиент предположит локальный часовой пояс клиента.
time.Time{}
илиsql.NullTime
будут преобразованы в эпоху соответственно. - При выборе временная зона колонки будет использоваться, если она установлена, при возврате значения
time.Time
. Если нет, будет использована временная зона сервера.
- При вставке значение отправляется в ClickHouse в формате UNIX timestamp. Если часовой пояс не указан, клиент предположит локальный часовой пояс клиента.
- Дата/Дата32
- При вставке временная зона любой даты учитывается при преобразовании даты в юникс-таймстамп, т.е. она будет сдвинута по временной зоне перед сохранением как дата, так как типы Дата не имеют локали в ClickHouse. Если это не указано в строковом значении, будет использован локальный часовой пояс.
- При выборе даты сканируются в экземпляры
time.Time{}
илиsql.NullTime{}
без информации о временной зоне.
Массив
Массивы должны быть вставлены как срезы. Правила типизации для элементов согласованы с правилами для примитивных типов, т.е. где это возможно, элементы будут преобразованы.
Указатель на срез должен быть предоставлен во время сканирования.
Карта
Карты должны быть вставлены как карты Golang с ключами и значениями, соответствующими правилам типов, определённым ранее.
Кортежи
Кортежи представляют собой группу колонок произвольной длины. Колонки могут быть либо явно названы, либо только указаны по типу, например:
Из этих подходов именованные кортежи предлагают большую гибкость. Хотя безымянные кортежи должны быть вставлены и прочитаны с использованием срезов, именованные кортежи также совместимы с картами.
Примечание: поддерживаются типизированные срезы и карты, при условии, что подколонки в именованном кортеже имеют одинаковые типы.
Вложенные
Вложенное поле эквивалентно массиву именованных кортежей. Использование зависит от того, установил ли пользователь flatten_nested в 1 или 0.
Установив flatten_nested в 0, вложенные колонки остаются как единый массив кортежей. Это позволяет пользователям использовать срезы карт для вставки и извлечения и произвольные уровни вложенности. Ключ карты должен соответствовать имени колонки, как показано в примере ниже.
Примечание: поскольку карты представляют кортеж, они должны быть типа map[string]interface{}
. Значения в настоящее время не имеют строгой типизации.
Полный пример - flatten_tested=0
Если используется значение по умолчанию 1 для flatten_nested
, вложенные колонки упрощаются до отдельных массивов. Это требует использования вложенных срезов для вставки и извлечения. Хотя произвольные уровни вложенности могут работать, это не поддерживается официально.
Полный пример - flatten_nested=1
Примечание: Вложенные колонки должны иметь одинаковые размеры. Например, в приведенном выше примере Col_2_2
и Col_2_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
Значение Nil в Go представляет собой NULL в ClickHouse. Это может быть использовано, если поле объявлено как Nullable. Во время вставки можно передать Nil для нормальной и Nullable версии колонки. Для первой будет сохранено значение по умолчанию для типа, например, пустая строка для строки. Для версии nullable будет сохранено значение NULL в ClickHouse.
Во время сканирования пользователь должен передать указатель на тип, который поддерживает nil, например, *string, чтобы представить значение nil для поля Nullable. В следующем примере col1, который является Nullable(String), соответственно получает строку. Это позволяет представить nil.
Клиент дополнительно поддерживает типы sql.Null*
, например, sql.NullInt64
. Эти типы совместимы с эквивалентными типами ClickHouse.
Большие целые числа - Int128, Int256, UInt128, UInt256
Числовые типы, превышающие 64 бита, представляются с использованием родного пакета Go big.
Сжатие
Поддержка методов сжатия зависит от используемого протокола. Для нативного протокола клиент поддерживает сжатие LZ4
и ZSTD
. Это выполняется только на уровне блоков. Сжатие может быть включено, добавив конфигурацию Compression
к соединению.
Дополнительные методы сжатия доступны при использовании стандартного интерфейса по HTTP. См. database/sql API - Сжатие для получения дополнительных сведений.
Привязка параметров
Клиент поддерживает привязку параметров для методов Exec
, Query
и QueryRow
. Как показано в примере ниже, это поддерживается с использованием именованных, пронумерованных и позиционных параметров. Мы предоставляем примеры этих параметров ниже.
Специальные случаи
По умолчанию срезы будут развернуты в разделенный запятыми список значений, если будут переданы в качестве параметра в запрос. Если пользователям требуется набор значений, которые следует вставить с обёрткой [ ]
, следует использовать ArraySet
.
Если требуются группы/кортежи с обёрткой ( )
, например, для использования с операторами IN, пользователи могут использовать GroupSet
. Это особенно полезно для случаев, когда требуется несколько групп, как показано в примере ниже.
Наконец, поля DateTime64 требуют точности, чтобы гарантировать, что параметры отображаются соответствующим образом. Уровень точности для поля неизвестен клиенту, однако пользователь должен предоставить его. Чтобы облегчить это, мы предоставляем параметр DateNamed
.
Использование контекста
Контексты Go предоставляют возможность передачи сроков, сигналов отмены и других значений, зависящих от запроса, через границы API. Все методы подключения принимают контекст в качестве своей первой переменной. В то время как предыдущие примеры использовали context.Background(), пользователи могут использовать эту возможность для передачи настроек и сроков, а также для отмены запросов.
Передача контекста, созданного с помощью withDeadline
, позволяет устанавливать временные ограничения на выполнение запросов. Обратите внимание, что это абсолютное время, и срок истечения только освободит подключение и отправит сигнал отмены в ClickHouse. Альтернативно можно использовать WithCancel
для явной отмены запроса.
Помощники clickhouse.WithQueryID
и clickhouse.WithQuotaKey
позволяют указывать идентификатор запроса и ключ квоты. Идентификаторы запросов могут быть полезны для отслеживания запросов в логах и для целей отмены. Ключ квоты может использоваться для наложения ограничений на использование ClickHouse на основе уникального значения ключа - см. Управление квотами для получения дополнительных деталей.
Пользователи также могут использовать контекст, чтобы гарантировать, что настройка применяется только для конкретного запроса, а не для всего соединения, как показано в Настройки подключения.
Наконец, пользователи могут контролировать размер буфера блоков через clickhouse.WithBlockSize
. Это переопределяет настройку уровня соединения BlockBufferSize
и контролирует максимальное количество блоков, которые декодируются и хранятся в памяти в любое время. Более крупные значения потенциально означают большую параллелизацию за счет памяти.
Примеры выше показаны ниже.
Информация о прогрессе/профиле/логах
Информация о прогрессе, профиле и логах может быть запрошена по запросам. Информация о прогрессе будет сообщать статистику о количестве строк и байт, которые были прочитаны и обработаны в ClickHouse. Напротив, информация профиля предоставляет сводку о данных, возвращенных клиенту, включая итоги по байтам (не сжатым), строкам и блокам. Наконец, информация журнала предоставляет статистику о потоках, например, использование памяти и скорость передачи данных.
Получение этой информации требует от пользователя использования Контекста, в который пользователь может передать функции обратного вызова.
Динамическое сканирование
Пользователи могут нуждаться в чтении таблиц, для которых они не знают схему или типы возвращаемых полей. Это часто встречается в случаях, когда выполняется анализ данных в режиме ad-hoc или создаются универсальные инструменты. Для достижения этого информация о типе колонки доступна в ответах на запросы. Это можно использовать с помощью отражения Go для создания экземпляров переменных с правильными типами, которые могут быть переданы в Scan.
Внешние таблицы
Внешние таблицы позволяют клиенту отправлять данные в ClickHouse с помощью запроса SELECT. Эти данные помещаются во временную таблицу и могут использоваться в самом запросе для оценки.
Чтобы отправить внешние данные клиенту с запросом, пользователю необходимо создать внешнюю таблицу через ext.NewTable
, прежде чем передать это через контекст.
Open Telemetry
ClickHouse позволяет передавать контекст трассировки как часть нативного протокола. Клиент позволяет создать Span через функцию clickhouse.withSpan
и передать это через Контекст для достижения этой цели.
Полные детали о том, как использовать трассировку, можно найти в разделе Поддержка OpenTelemetry.
API Базы Данных/SQL
Стандартный API database/sql
позволяет пользователям использовать клиент в сценариях, где код приложения должен быть агностичен к базам данных, соответствуя стандартному интерфейсу. Это имеет свои затраты - дополнительные слои абстракции и косвенности и примитивы, которые не обязательно согласуются с ClickHouse. Эти затраты, тем не менее, обычно приемлемы в ситуациях, когда инструменты должны подключаться к нескольким базам данных.
Кроме того, этот клиент поддерживает использование HTTP в качестве транспортного уровня - данные все еще будут кодироваться в нативном формате для достижения оптимальной производительности.
Следующая структура документации стремится зеркалить структуру документации для API ClickHouse.
Полные примеры кода для стандартного API можно найти здесь.
Подключение
Подключение можно выполнить либо через строку DSN с форматом clickhouse://<host>:<port>?<query_option>=<value>
и метод Open
, либо через метод clickhouse.OpenDB
. Последний не является частью спецификации database/sql
, но возвращает экземпляр sql.DB
. Этот метод предоставляет функциональность, такую как профилирование, для которой нет очевидных средств раскрытия через спецификацию database/sql
.
Для всех последующих примеров, если не указано иное, мы предполагаем, что переменная conn
ClickHouse была создана и доступна.
Настройки подключения
В следующую строку 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-соединений. Если любое из этих сжатий включено, сжатие выполняется на блоках во время вставки и для ответов на запросы. Другие запросы, такие как ping или запросы, останутся несжатыми. Это согласуется с параметрами lz4
и zstd
.
Если используется метод OpenDB
для установки соединения, можно передать конфигурацию сжатия. Это включает возможность указать уровень сжатия (см. ниже). Если подключаетесь через 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, это достигается с помощью вариантов методов, таких как Exec
, которые по умолчанию используют фоновый контекст, имеют вариант ExecContext
, в который можно передать контекст в качестве первого параметра. Это позволяет передавать контекст на любом этапе потока приложения. Например, пользователи могут передавать контекст при установлении соединения через ConnContext
или при запросе строки через QueryRowContext
. Примеры всех доступных методов показаны ниже.
Для получения дополнительной информации о использовании контекста для передачи сроков, сигналов отмены, идентификаторов запросов, ключей квоты и настроек соединения см. Использование контекста для ClickHouse API.
Сессии
Хотя родные соединения по сути имеют сессию, соединения по HTTP требуют от пользователя создания идентификатора сессии для передачи в контексте в качестве настройки. Это позволяет использовать функции, такие как временные таблицы, которые привязаны к сессии.
Динамическое сканирование
Аналогично ClickHouse API, информация о типах колонок доступна для того, чтобы позволить пользователям создавать экземпляры переменных правильного типа во время выполнения, которые могут быть переданы в Scan. Это позволяет считывать колонки, где тип неизвестен.
Внешние таблицы
Внешние таблицы позволяют клиенту отправлять данные в ClickHouse с помощью запроса SELECT
. Эти данные помещаются во временную таблицу и могут быть использованы в самом запросе для оценки.
Чтобы отправить внешние данные клиенту с запросом, пользователю необходимо создать внешнюю таблицу через ext.NewTable
, прежде чем передать ее через контекст.
Open Telemetry
ClickHouse позволяет передавать контекст трассировки как часть родного протокола. Клиент позволяет создать Span через функцию clickhouse.withSpan
и передать его через Контекст для достижения этой цели. Это не поддерживается, когда в качестве транспорта используется HTTP.
Советы по производительности
- Используйте ClickHouse API, где это возможно, особенно для примитивных типов. Это избегает значительных затрат на рефлексию и косвенные вызовы.
- Если вы читаете большие наборы данных, рассмотрите возможность изменения
BlockBufferSize
. Это увеличит объем памяти, но позволит декодировать больше блоков параллельно во время итерации по строкам. Значение по умолчанию 2 является консервативным и минимизирует объем памяти. Высокие значения будут означать больше блоков в памяти. Это требуется тестирования, так как разные запросы могут производить разные размеры блоков. Это также можно установить на уровне запроса через Контекст. - Будьте конкретны с вашими типами при вставке данных. Хотя клиент стремится быть гибким, например, позволяя строкам анализироваться для UUID или IP, это требует проверки данных и влечет за собой расходы во время вставки.
- Используйте вставки с колонками, где это возможно. Эти вставки также должны быть строго типизированы, избегая необходимости клиенту конвертировать ваши значения.
- Следуйте рекомендациям ClickHouse для оптимальной производительности вставок.