ORDER BY содержит
- список выражений, например
ORDER BY visits, search_phrase, - список чисел, ссылающихся на столбцы в предложении
SELECT, напримерORDER BY 2, 1, или ALL, что означает все столбцы предложенияSELECT, напримерORDER BY ALL.
ALL, установите настройку enable_order_by_all = 0.
Для предложения ORDER BY можно указать модификатор DESC (по убыванию) или ASC (по возрастанию), который определяет направление сортировки.
Если явный порядок сортировки не указан, по умолчанию используется ASC.
Направление сортировки применяется к отдельному выражению, а не ко всему списку, например ORDER BY Visits DESC, SearchPhrase.
Кроме того, сортировка выполняется с учетом регистра.
Строки с одинаковыми значениями в выражениях сортировки возвращаются в произвольном и недетерминированном порядке.
Если предложение ORDER BY опущено в операторе SELECT, порядок строк также будет произвольным и недетерминированным.
Сортировка специальных значений
NaN и NULL:
- По умолчанию или с модификатором
NULLS LAST: сначала значения, затемNaN, затемNULL. - С модификатором
NULLS FIRST: сначалаNULL, затемNaN, а затем остальные значения.
Пример
SELECT * FROM t_null_nan ORDER BY y NULLS FIRST, чтобы получить:
Поддержка collation
ORDER BY SearchPhrase COLLATE 'tr' — для сортировки по ключевому слову в порядке возрастания с использованием турецкого алфавита, без учета регистра, при условии, что строки представлены в кодировке UTF-8. COLLATE можно независимо указывать или не указывать для каждого выражения в ORDER BY. Если указан ASC или DESC, COLLATE указывается после него. При использовании COLLATE сортировка всегда выполняется без учета регистра.
COLLATE поддерживается в LowCardinality, Nullable, Array и Tuple.
Мы рекомендуем использовать COLLATE только для окончательной сортировки небольшого числа строк, поскольку сортировка с COLLATE менее эффективна, чем обычная сортировка по байтам.
Примеры collation
Query
Response
Query
Response
Query
Response
Query
Response
Response
Query
Response
Подробности реализации
ORDER BY указан достаточно небольшой LIMIT. В противном случае объём используемой памяти пропорционален объёму данных, которые нужно отсортировать. При распределённой обработке запроса, если GROUP BY отсутствует, сортировка частично выполняется на удалённых серверах, а результаты объединяются на сервере, инициировавшем запрос. Это означает, что при распределённой сортировке объём данных может превышать объём памяти одного сервера.
Если оперативной памяти недостаточно, сортировку можно выполнять во внешней памяти (создавая временные файлы на диске). Для этого используйте настройку max_bytes_before_external_sort. Если она установлена в 0 (значение по умолчанию), внешняя сортировка отключена. Если она включена, то когда объём данных для сортировки достигает указанного количества байт, собранные данные сортируются и записываются во временный файл. После чтения всех данных все отсортированные файлы объединяются, и результаты выводятся. Файлы записываются в каталог /var/lib/clickhouse/tmp/, указанный в конфигурации (по умолчанию, но вы можете изменить это с помощью параметра tmp_path). Также можно использовать сброс на диск только в том случае, если запрос превышает лимиты памяти: например, max_bytes_ratio_before_external_sort=0.6 включит сброс на диск только после того, как запрос достигнет 60% лимита памяти (пользователь/сервер).
При выполнении запроса может использоваться больше памяти, чем задано в max_bytes_before_external_sort. Поэтому значение этой настройки должно быть значительно меньше, чем max_memory_usage. Например, если ваш сервер имеет 128 ГБ оперативной памяти и вам нужно выполнить один запрос, установите max_memory_usage в 100 ГБ, а max_bytes_before_external_sort — в 80 ГБ.
Внешняя сортировка работает значительно менее эффективно, чем сортировка в оперативной памяти.
Оптимизация чтения данных
ORDER BY имеет префикс, совпадающий с ключом сортировки таблицы, запрос можно оптимизировать с помощью настройки optimize_read_in_order.
Когда настройка optimize_read_in_order включена, сервер ClickHouse использует индекс таблицы и читает данные в порядке ключа ORDER BY. Это позволяет избежать чтения всех данных, если указан LIMIT. Поэтому запросы к большим объемам данных с небольшим LIMIT выполняются быстрее.
Оптимизация работает как с ASC, так и с DESC, и не работает вместе с оператором GROUP BY и модификатором FINAL.
Когда настройка optimize_read_in_order отключена, сервер ClickHouse не использует индекс таблицы при обработке запросов SELECT.
Рекомендуется вручную отключать optimize_read_in_order при выполнении запросов с предложением ORDER BY, большим LIMIT и условием WHERE, из-за которого приходится прочитать огромное количество записей, прежде чем будут найдены нужные данные.
Оптимизация поддерживается в следующих движках таблиц:
- MergeTree (включая materialized views),
- Merge,
- Buffer
MaterializedView оптимизация работает для представлений вида SELECT ... FROM merge_tree_table ORDER BY pk. Но она не поддерживается для запросов вида SELECT ... FROM view ORDER BY pk, если запрос представления не содержит предложения ORDER BY.
Модификатор ORDER BY Expr WITH FILL
WITH FILL можно указать после ORDER BY expr с необязательными параметрами FROM expr, TO expr и STEP expr.
Все отсутствующие значения в столбце expr будут последовательно заполнены, а остальные столбцы — значениями по умолчанию.
Чтобы заполнить несколько столбцов, добавьте модификатор WITH FILL с необязательными параметрами после имени каждого поля в разделе ORDER BY.
Query
WITH FILL можно применять к полям с типами Numeric (все виды float, decimal, int) или Date/DateTime. При применении к полям String пропущенные значения заполняются пустыми строками.
Если FROM const_expr не задан, для последовательности заполнения используется минимальное значение поля expr из ORDER BY.
Если TO const_expr не задан, для последовательности заполнения используется максимальное значение поля expr из ORDER BY.
Если задан STEP const_numeric_expr, то const_numeric_expr интерпретируется as is для числовых типов, как days для типа Date и как seconds для типа DateTime. Также поддерживается тип данных INTERVAL, представляющий интервалы даты и времени.
Если STEP const_numeric_expr опущен, то для последовательности заполнения используется 1.0 для числового типа, 1 day для типа Date и 1 second для типа DateTime.
Если задан STALENESS const_numeric_expr, запрос будет генерировать строки, пока разница по сравнению с предыдущей строкой в исходных данных не превысит const_numeric_expr.
INTERPOLATE можно применять к столбцам, не участвующим в ORDER BY WITH FILL. Такие столбцы заполняются на основе значений предыдущих полей с применением expr. Если expr не указан, будет повторяться предыдущее значение. Если список опущен, будут включены все допустимые столбцы.
Пример запроса без WITH FILL:
Query
Response
WITH FILL:
Query
Response
ORDER BY field2 WITH FILL, field1 WITH FILL заполнение будет выполняться в порядке полей в предложении ORDER BY.
Пример:
Query
Response
d1 не заполняется и использует значение по умолчанию, потому что для d2 нет повторяющихся значений, и последовательность для d1 не может быть корректно вычислена.
Следующий запрос с изменённым полем в ORDER BY:
Query
Response
INTERVAL со значением 1 день для каждого значения, заполняемого в столбце d1:
Query
Response
STALENESS:
Query
Response
STALENESS 3:
Query
Response
INTERPOLATE:
Query
Response
INTERPOLATE:
Query
Response
Заполнение с группировкой по префиксу сортировки
sensor_id в качестве префикса сортировки при заполнении столбца timestamp:
value было интерполировано значение 9999 — просто чтобы заполненные строки были заметнее.
Это поведение управляется настройкой use_with_fill_by_sorting_prefix (включена по умолчанию)