Всевозможные объекты: функции, агрегатные функции, типы данных, движки таблиц, и т. п. достаются по имени из фабрик. Часто пользователь допускает опечатку. Например, вместо SELECT count(*)
может быть написано SELECT cunt(*)
. В случае опечатки, необходимо в текст сообщения добавлять указание на ближайшие варианты. Для реализации можно использовать расстояние Левенштейна и полный перебор, или (лучше) - триграмный индекс. Подсказки выдаём, если указанное имя отличается от существующего на 1..2 буквы. Сортируем возможные варианты в порядке похожести. Для того, чтобы это работало во всех фабриках, может быть, потребуется обобщить их.
Geohash - способ преобразования географических координат в строку, так что отображение обладает свойством локальности. https://en.wikipedia.org/wiki/Geohash В качестве библиотеки следует использовать эту: https://github.com/yinqiwen/geohash-int Необходимо добавить функции для перевода в обе стороны, а также для числового и текстового вариантов.
Необходима функция вида roundDown(x, [0, 18, 24, 36, 65])
- округление вниз до числа из явно указанного списка.
Пример: округление возраста пользователя.
(сделали энтропию) Агрегатные функции для статистических тестов (e.g. тест нормальности распределения) и статистик (e.g. энтропия).
В ClickHouse есть понятие - состояние вычисления агрегатной функции. Состояния агрегатных функций можно записывать в таблицы, складывать, финализировать и т. п. https://clickhouse.yandex/docs/ru/data_types/nested_data_structures/aggregatefunction/
Получить состояние агрегатной функции можно с помощью комбинатора State: https://clickhouse.yandex/docs/ru/query_language/agg_functions/combinators/#-state Но хотелось бы добавить ещё более простой способ получения состояния агрегатной функции.
Например:
createAggregationState('groupArray')
- создать пустое (начальное) состояние агрегатной функции.
createAggregationState('groupArray', 1)
- создать состояние агрегатной функции, в котором агрегировано одно значение 1.
createAggregationState('argMax', ('hello', 123))
- то же самое для агрегатных функций, принимающих несколько аргументов.
ClickHouse/ClickHouse#2011 Нужно сравнивать Date и DateTime так, как будто Date расширено до DateTime на начало суток в том же часовом поясе.
makeDate(year, month, day)
makeDateTime(year, month, day, hour, minute, second, [timezone])
changeYear(datetime, 2019)
format('Hello {2} World {1}', x, y)
https://github.com/intel/hyperscan Реализовать на основе этой библиотеки функцию для матчинга сразу большого количества регулярных выражений.
SELECT least(123, 456)
- работает.
SELECT least('123', '456')
- не работает. Надо сделать.
Делаем с помощью IColumn::compareAt
для одинаковых типов и с помощью castColumn
, getLeastSuperType
для разных.
flatten([[1, 2, 3], [4, 5]]) = [1, 2, 3, 4, 5]
isValidUTF8
возвращает 1, если строка содержит набор байт в кодировке UTF-8.
toValidUTF8
- заменяет последовательности байт, не соответствующие кодировке UTF-8, на replacement character.
Возвращает инкрементальное число для повторно встречающихся значений key.
groupConcat(x, ',')
- собрать из переданных значений x строку, разделённую запятыми.
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-add
Удаление пробелов с концов строк. Возможность указать другой вариант вместо пробела.
Функции positionReverse, positionUTF8Reverse, positionCaseInsensitiveReverse, positionCaseInsensitiveUTF8Reverse.
position с конца строки.
bitAnd, bitOr, bitNot, bitXor для значения типа FixedString, интерпретируемого как набор бит.
indexOf(arr, 'hello')
, indexOf(arr, 1)
должны работать, если arr имеет тип Array(Enum8('hello' = 1, 'world' = 2))
arrayWithConstant(3, 'hello') = ['hello', 'hello', 'hello']
Пример: avgDistinct(x)
- вычислить среднее по всем различным переданным значениям.
Если известно, что читаемый из файла диапазон больше порога, использовать для чтения MMapReadBuffer.
Смотрим, сколько на сервере оперативки. Если max_memory_usage, max_memory_usage_for_all_queries ограничены, но больше 90% (настройка) от имеющейся оперативки, то уменьшать их и выводить предупреждение в лог. Аналогично для кэшей: mark_cache, uncompressed_cache.
Если владелец директории с данными - не текущий пользователь - кидать исключение и завершать работу. Защита от случая, когда сервер запускают из под root, он создаёт файлы с неправильными правами, а потом по-нормальному запущенный сервер не может работать.
Если uid процесса 0, то выводить сообщение о том, что надо писать sudo -u clickhouse
.
Если сервер собран с поддержкой SSE 4.2, 4.1, 4, SSSE 3, SSE 3, то как можно ближе к началу работы, запускаем функцию, которая выполняет нужную инструкцию в качестве теста (asm volatile вставка), а до этого ставим обработчик сигнала SIGILL, который в случае невозможности выполнить инструкцию, сделает siglongjmp, позволит нам вывести понятное сообщение в лог и завершить работу. Замечание: /proc/cpuinfo зачастую не содержит актуальную информацию.
Смотрим, что все файлы в прикрепляемых кусках от правильного пользователя.
Content-Encoding: br
В ClickHouse есть возможность указать collation для сортировки строк. Это не работает для Nullable(String)
.
Добавляем счётчики всех ошибок (ErrorCodes) по аналогии с ProfileEvents. Кроме количества запоминаем также время последней ошибки, стек трейс, сообщение. Добавляем системную таблицу system.errors. Отправка в Graphite.
Экспериментальные алгоритмы сжатия. Сейчас ClickHouse поддерживает только lz4 и zstd.
(сделали) Проверить возможность использования pdqsort вместо std::sort для полной comparison-based сортировки.
В случае, когда есть ORDER BY без LIMIT, это может позволить слегка увеличить производительность.
Атомарно (под блокировкой) удаляет таблицу перед созданием новой, если такая была.
SELECT 1 IN (SELECT -1 UNION ALL SELECT 1)
- сейчас не работает.
Возможность создать таблицу с таким же типом и структурой, как табличная функция.
https://clickhouse.yandex/docs/ru/query_language/select/#limit-n-by
LIMIT 100, 10 BY RegionID
- выдать не более 10 строк для каждого RegionID, но пропустив первые 100 строк.
Состояния агрегатных функций могут быть записаны в дамп и считаны из него. Но десериализация состояний агрегатных функций небезопасна. Аккуратно выбранные пользовательские данные могут привести к segfault или порче памяти. Поэтому нужно просто сделать настройку, которая запрещает читать AggregateFunction из пользовательских данных.
Возможность вставки значений типа AggregateFunction в виде кортежа значений аргументов, а не бинарного дампа состояния, под настройкой.
Во входных данных в запросе INSERT должна быть возможность передать значение типа AggregateFunction не в виде сериализованного состояния, а в виде аргументов, которые будут агрегированы, для формирования этого состояния.
https://clickhouse.yandex/docs/en/query_language/create/#create-table
INSERT INTO table (column1, column2, ...)
- если column - это ALIAS столбец, и если выражение для ALIAS тривиально (просто ссылается на другой столбец), то разрешить использовать его вместо другого столбца в запросе INSERT.
Запретить модификацию данных в партиции. На партицию ставится флаг, что она заблокирована. В неё нельзя делать INSERT и ALTER. С файлов снимается доступ на запись.
Сейчас вместо NULL подставляются значения по-умолчанию. Разрешить загружать Nullable типы. Под настройкой.
Возможность вывозить время выполнения запроса, а также красивый прогресс-бар для каждого запроса.
Возможность писать LIMIT 1 + 2
. То же самое для LIMIT BY
.
(сделали) Добавить информацию об exp-smoothed количестве ошибок соединений с репликами в таблицу system.clusters.
У нас есть счётчик ошибок соединения с серверами для failover. Надо сделать его видимым для пользователя.
Возможность легко импортировать данные из MongoDB.
В заголовке CSV, TSV могут быть указаны имена столбцов. Сейчас они полностью игнорируются. Надо учитывать, под настройкой.
(сделали) Возможность включить использование ключа шардирования для исключения шардов при распределённых SELECT-ах.
Отсекать лишние шарды при распределённых запросах, если в запросе есть соответствующие условия.
При INSERT SELECT, запрос SELECT может выполняться параллельно, но все данные будут передаваться на вставку в INSERT в один поток. Хотя некоторые таблицы (семейства MergeTree) поддерживают параллельную вставку. Необходимо сделать настройку для максимального количества потоков для INSERT.
ORDER BY x LIMIT 10 WITH TIES
- возвращает первые 10 строк в порядке x, а также все следующие за ними строки, у которых значение x равно десятой.
SELECT 'hello\nworld' AS x, 123 AS y
┌─x──────────┬───y─┐
│ hello
world │ 123 │
└────────────┴─────┘
А надо так:
┌─x─────┬───y─┐
│ hello…│ 123 │
│…world │ │
└───────┴─────┘
Это заметно при работе с серверами с большим пингом. Прогресс бар не должен мерцать. Наверное, надо просто вместо очистки строки, перемещать курсор в начало, не очищая её.
В system.asynchronous_metrics - суммарный размер арен.
https://clickhouse.yandex/docs/en/query_language/alter/ - см. FREEZE.
ALTER TABLE t FREEZE
- атомарно применить операцию FREEZE ко всем партициям.
Пишем текстовые логи ClickHouse в системную таблицу в структурированном виде. См. SystemLog.h, cpp.
https://clickhouse.yandex/benchmark.html Потребуется доступ на сервер Яндекса.
https://clickhouse.yandex/docs/en/operations/table_engines/external_data/ Не работает, если открыть clickhouse-client в интерактивном режиме и делать несколько запросов.
Хотим по Ctrl+C получить те данные, которые успели обработаться.
(сделали) Недостатки юзабилити: у clickhouse-client отсутствует сокращённая опция -C, как вариант --config-file; Недостатки юзабилити, если пользователь не может прочитать конфиг клиента.
Функция sequenceMatch поддерживает слишком сложные выражения, из-за чего в ней возникает возможность backtracking экспоненциальной сложности. Необходимо сделать функцию, которая будет поддерживать только более простые выражения.
SELECT * FROM loop(database, table)
Читает данные из таблицы в бесконечном цикле.
(сделали) Поддержка чтения дат в формате '01-OCT-2015' и '01.10.2015' в функции parseDateTimeBestEffort.
(сделали) Возможность задавать параметры соединений для табличных функций, движков таблиц и для реплик из отдельных разделов конфигурации.
Функция serialize для implementation specific non portable non backwards compatible сериализации любого типа данных в набор байт.
Как arrayEnumerateUniq, но смотрит на самые глубокие элементы вложенных массивов.