#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 Да. повлияет, конечно, но сортировка-это то, что Улей может делать очень эффективно, вы не можете делать это просто так. Обычно это должен быть какой-то кандидат на первичный ключ, подумайте о редизайне