Перейти к основному содержимому
Перейти к основному содержимому

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.21.17, 1.18
>= 2.31.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. Если нет, будет использована временная зона сервера.
  • Дата/Дата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 для оптимальной производительности вставок.