Перейти к основному содержанию
Файлы в формате Tab Separated Value, или TSV, широко распространены и могут содержать имена полей в первой строке. ClickHouse умеет загружать TSV-файлы, а также выполнять запросы к ним без загрузки самих файлов. В этом руководстве рассматриваются оба варианта. Если вам нужно выполнять запросы к CSV-файлам или загружать их, подойдут те же методы — просто замените TSV на CSV в аргументах формата. В ходе работы с этим руководством вы:
  • Исследуете: выполните запросы к структуре и содержимому TSV-файла.
  • Определите целевую схему ClickHouse: выберите подходящие типы данных и сопоставьте с ними существующие данные.
  • Создадите таблицу ClickHouse.
  • Предварительно обработаете и передадите потоково данные в ClickHouse.
  • Выполните несколько запросов к ClickHouse.
Набор данных, используемый в этом руководстве, предоставлен командой NYC Open Data и содержит данные обо «всех подтверждённых преступлениях категорий felony, misdemeanor и violation, о которых сообщалось в New York City Police Department (NYPD)». На момент написания файл данных имеет размер 166 МБ, но регулярно обновляется. Источник: data.cityofnewyork.us Условия использования: https://www1.nyc.gov/home/terms-of-use.page

Необходимые условия

Примечание о командах, описанных в этом руководстве

В этом руководстве используются два типа команд:
  • Некоторые команды выполняют запросы к TSV-файлам; их запускают в командной строке.
  • Остальные команды выполняют запросы к ClickHouse; их запускают в clickhouse-client или в интерфейсе Play.
Примеры в этом руководстве предполагают, что вы сохранили файл в формате TSV по пути ${HOME}/NYPD_Complaint_Data_Current__Year_To_Date_.tsv; при необходимости скорректируйте команды.

Ознакомьтесь с файлом в формате TSV

Прежде чем приступить к работе с базой данных ClickHouse, ознакомьтесь с данными.

Посмотрите на поля в исходном файле в формате TSV

Это пример команды для выполнения запроса к файлу в формате TSV, но пока не запускайте её.
Query
Пример ответа
В большинстве случаев приведённая выше команда покажет, какие поля во входных данных являются числовыми, какие — строковыми, а какие — кортежами. Но так бывает не всегда. Поскольку ClickHouse обычно работает с датасетами, содержащими миллиарды записей, по умолчанию для определения схемы анализируется лишь ограниченное число строк (100), чтобы не выполнять парсинг миллиардов строк. Приведённый ниже результат может отличаться от того, что увидите вы, так как датасет обновляется несколько раз в год. Если заглянуть в словарь данных, можно увидеть, что CMPLNT_NUM указан как текстовое, а не числовое поле. Переопределив значение по умолчанию — 100 строк для определения схемы — с помощью настройки SETTINGS input_format_max_rows_to_read_for_schema_inference=2000, можно получить более точное представление о содержимом.Примечание: начиная с версии 22.5 значением по умолчанию теперь являются 25 000 строк для определения схемы, поэтому изменяйте эту настройку только если используете более старую версию или если вам нужно, чтобы в выборку попало более 25 000 строк.
Выполните эту команду в командной строке. Для запроса данных в загруженном файле в формате TSV вы будете использовать clickhouse-local.
Query
Response
На этом этапе следует проверить, что столбцы в файле в формате TSV соответствуют именам и типам, указанным в разделе Столбцы в этом наборе данных на странице набора данных. Типы данных здесь не слишком конкретны: для всех числовых полей задан Nullable(Float64), а для всех остальных — Nullable(String). При создании таблицы ClickHouse для хранения данных можно указать более подходящие и эффективные типы.

Определите подходящую схему

Чтобы понять, какие типы следует использовать для полей, нужно знать, как выглядят данные. Например, поле JURISDICTION_CODE содержит числовое значение: следует ли использовать UInt8, Enum или подойдет Float64?
Query
Response
Ответ на запрос показывает, что JURISDICTION_CODE хорошо укладывается в UInt8. Аналогично посмотрите на некоторые поля типа String и проверьте, не лучше ли представить их как поля DateTime или LowCardinality(String). Например, поле PARKS_NM описывается как “Название парка, игровой площадки или зелёной зоны в Нью-Йорке, где произошло событие, если применимо (парки штата не включены)”. Названия парков в Нью-Йорке могут быть хорошим кандидатом для LowCardinality(String):
Query
Response
Обратите внимание на названия некоторых парков:
Query
Response
Используемый на момент написания набор данных содержит лишь несколько сотен различных парков и игровых площадок в столбце PARK_NM. Это немного, если учитывать рекомендацию LowCardinality — не более 10 000 различных строковых значений в поле LowCardinality(String).

Поля DateTime

Судя по разделу Columns in this Dataset на странице набора данных, в нём есть поля даты и времени, указывающие начало и окончание зарегистрированного события. Просмотр минимальных и максимальных значений CMPLNT_FR_DT и CMPLT_TO_DT позволяет понять, всегда ли эти поля заполнены:
Query
Response
Query
Response
Query
Response
Query
Response

Составьте план

На основе приведённого выше анализа:
  • JURISDICTION_CODE следует привести к типу UInt8.
  • PARKS_NM следует привести к типу LowCardinality(String)
  • CMPLNT_FR_DT и CMPLNT_FR_TM всегда заполнены (возможно, со временем по умолчанию 00:00:00)
  • CMPLNT_TO_DT и CMPLNT_TO_TM могут быть пустыми
  • В исходных данных дата и время хранятся в отдельных полях
  • Даты имеют формат mm/dd/yyyy
  • Время имеет формат hh:mm:ss
  • Дату и время можно объединить в типы DateTime
  • Есть даты раньше 1 января 1970 года, а это значит, что нужен 64-битный DateTime
Нужно внести ещё много изменений в типы, и все их можно определить, выполнив те же шаги анализа. Посмотрите на количество различных строковых значений в поле, минимальные и максимальные числовые значения и примите решение. В схеме таблицы, приведённой далее в руководстве, много строковых полей низкой кардинальности и беззнаковых целочисленных полей, и очень мало чисел с плавающей запятой.

Объедините поля даты и времени

Чтобы объединить поля даты и времени CMPLNT_FR_DT и CMPLNT_FR_TM в одну строку String, которую затем можно преобразовать в DateTime, выберите эти два поля, соединив их оператором конкатенации: CMPLNT_FR_DT || ' ' || CMPLNT_FR_TM. Аналогичным образом обрабатываются поля CMPLNT_TO_DT и CMPLNT_TO_TM.
Query
Response

Преобразование строки с датой и временем в тип DateTime64

Ранее в этом руководстве мы выяснили, что в файле в формате TSV есть даты до 1 января 1970 года, а это значит, что для них нужен 64-битный тип DateTime. Даты также нужно преобразовать из формата MM/DD/YYYY в формат YYYY/MM/DD. И то и другое можно сделать с помощью parseDateTime64BestEffort().
Query
Строки 2 и 3 выше содержат результат конкатенации из предыдущего шага, а строки 4 и 5 выше разбирают строки в DateTime64. Поскольку время окончания жалобы может отсутствовать, используется parseDateTime64BestEffortOrNull.
Response
Показанные выше даты 1925 — результат ошибок в данных. В исходных данных есть несколько записей с датами в диапазоне 1019 - 1022, хотя должно быть 2019 - 2022. Они сохраняются как 1 января 1925 года, поскольку это самая ранняя дата, поддерживаемая 64-битным DateTime.

Создание таблицы

Принятые выше решения о типах данных, используемых для столбцов, отражены в приведённой ниже схеме таблицы. Нам также нужно определить ORDER BY и PRIMARY KEY для таблицы. Как минимум один из параметров ORDER BY или PRIMARY KEY должен быть указан. Ниже приведены рекомендации по выбору столбцов для включения в ORDER BY; более подробная информация приведена в разделе Следующие шаги в конце этого документа.

Секции ORDER BY и PRIMARY KEY

  • Кортеж ORDER BY должен включать поля, используемые в фильтрах запроса
  • Чтобы максимально увеличить сжатие на диске, кортеж ORDER BY следует упорядочить по возрастанию мощности
  • Если PRIMARY KEY задан, этот кортеж должен быть подмножеством кортежа ORDER BY
  • Если указан только ORDER BY, тот же кортеж будет использоваться как PRIMARY KEY
  • Индекс PRIMARY KEY создается по кортежу PRIMARY KEY, если он указан, иначе — по кортежу ORDER BY
  • Индекс PRIMARY KEY хранится в оперативной памяти
Исходя из набора данных и вопросов, на которые можно будет ответить с его помощью, мы можем решить, что хотим анализировать типы зарегистрированных преступлений по времени в пяти боро Нью-Йорка. Тогда в ORDER BY можно включить следующие поля: Запросим файл в формате TSV, чтобы определить мощность трех столбцов-кандидатов:
Query
Response
При сортировке по мощности выражение ORDER BY принимает вид:
В таблице ниже будут использоваться более понятные имена столбцов, а приведённые выше имена будут сопоставлены с
С учётом изменений в типах данных и кортежа ORDER BY структура таблицы будет такой:

Поиск первичного ключа таблицы

База данных ClickHouse system, а точнее system.table, содержит всю информацию о только что созданной таблице. Этот запрос показывает ORDER BY (ключ сортировки) и PRIMARY KEY:
Ответ

Предварительная обработка и импорт данных

Для предварительной обработки данных мы будем использовать инструмент clickhouse-local, а для их загрузки — clickhouse-client.

Используемые аргументы clickhouse-local

table='input' встречается в аргументах clickhouse-local ниже. clickhouse-local принимает указанный вход (cat ${HOME}/NYPD_Complaint_Data_Current__Year_To_Date_.tsv) и выполняет вставку этих данных в таблицу. По умолчанию таблица называется table. В этом руководстве имя таблицы задано как input, чтобы поток данных был понятнее. Последний аргумент clickhouse-local — это запрос, который выбирает данные из таблицы (FROM input), а затем передаётся по конвейеру в clickhouse-client для заполнения таблицы NYPD_Complaint.

Проверьте данные

Набор данных обновляется один или несколько раз в год, поэтому ваши результаты могут не совпадать с приведёнными в этом документе.
Query
Response
Объём данных в ClickHouse составляет всего 12 % от размера исходного файла в формате TSV; сравните размер исходного файла в формате TSV с размером таблицы:
Query
Response

Выполните несколько запросов

Запрос 1. Сравните количество жалоб по месяцам

Query
Response

Запрос 2. Сравните общее число жалоб по боро

Query
Response

Следующие шаги

Практическое введение в разреженные первичные индексы в ClickHouse рассказывает о различиях между индексированием в ClickHouse и в традиционных реляционных базах данных, о том, как ClickHouse строит и использует разреженный первичный индекс, а также о лучших практиках индексирования.
Последнее изменение 19 июня 2026 г.