как выполнить глобальную сортировку без уникального ключа в Presto

#sql-order-by #presto #row-number #deterministic #non-deterministic

#sql-порядок-по #presto #номер строки #детерминированный #недетерминированный

Вопрос:

В моем случае у меня есть несколько таблиц-ульев, столбец разделов(dt) является единственным столбцом, содержащимся в каждой таблице.

Я выполняю sql ниже в hive

 SELECT * FROM ( SELECT row_number() over(ORDER BY T.dt) as row_num,T.* FROM  (select * from ods.test_table where dt='2021-09-06') as T) TT  WHERE TT.row_num BETWEEN 1 AND 10  

Я каждый раз получаю один и тот же результат.

Но я выполняю sql в Presto, результат не тот же самый. Я думаю, что основной причиной является отсутствие в моей таблице уникального ключа.

Можно ли выполнить глобальный запрос без уникального ключа в Presto?

Ответ №1:

Вы вычисляете номер строки

 row_number() over(ORDER BY T.dt)  

и ПОРЯДОК ПО столбцам всегда один и тот же dt=’2021-09-06′. В этом случае row_number имеет недетерминированное поведение и может присваивать одни и те же номера разным строкам от запуска к запуску.

Тот факт, что вы всегда получаете одни и те же результаты в Hive, является совпадением, вероятно, вы всегда работаете с одинаковым количеством разбиений или даже на одном картографе, который работает однопоточно и выдает результаты, которые выглядят как детерминированные. Presto может иметь разный параллелизм, и это влияет на то, какие строки сначала передаются в row_number.

Вы можете попытаться изменить что-то в конфигурации разделения, чтобы увеличить количество сопоставителей или увеличить размер данных, и вы сможете воспроизвести недетерминированное поведение, многие сопоставители, работающие параллельно в сильно загруженном кластере, будут выполняться с разной скоростью, и разные строки будут передаваться в row_number.

Чтобы получить детерминированные результаты, вы можете добавить несколько столбцов в ПОРЯДОК, по которому будет определяться порядок строк. Если у вас нет таких столбцов, это означает, что у вас может быть любое количество полных дубликатов.

Даже если у вас нет уникального ключа, row_number даст детерминированные результаты, если ВСЕ столбцы расположены в порядке по.

Рассмотрим этот набор данных:

 Col1 Col2 Col3 1 1 2 1 1 2 1 1 3 1 1 3  

row_number() over(ORDER BY col1) as rn может создавать все 4 строки, упорядоченные по-разному при каждом запуске (предположим, что набор данных очень большой, и одновременно выполняется много сопоставителей, некоторые сопоставители могут завершиться быстрее, некоторые могут выйти из строя и перезапуститься). Конечно, если у вас есть такой небольшой набор данных и вы всегда обрабатываете его в одном процессе, в одном потоке, результат будет одинаковым, но в целом базы данных работают не так.

То же самое о row_number() over(ORDER BY col1, col2)

Но в случае row_number() over(ORDER BY col1, col2, col3) — вы всегда будете получать один и тот же набор данных, гарантированно.

Таким образом, решение состоит в том, чтобы использовать столько порядков по столбцам, сколько необходимо для определения порядка строк. В худшем случае, если у вас есть полные дубликаты, все столбцы должны быть добавлены в ПОРЯДОК ПО, дубликаты будут упорядочены вместе, и результат будет детерминированным.

Комментарии:

1. добавление порядка по столбцам может решить мою проблему, но я думаю, что это повлияет на производительность

2. @YonghuiLu Да. повлияет, конечно, но сортировка-это то, что Улей может делать очень эффективно, вы не можете делать это просто так. Обычно это должен быть какой-то кандидат на первичный ключ, подумайте о редизайне