У нас есть следующий сценарий:
- У нас есть таблица, содержащая ок. 15 миллиардов записей. Он не был явно разделен при создании.
- Мы создаем копию этой таблицы с разделами, надеясь на более быстрое чтение определенных типов запросов.
- Наши таблицы находятся в облаке Databricks, и мы используем Databricks Delta.
- Обычно мы фильтруем по двум столбцам, один из которых является идентификатором объекта (350 тыс. Различных значений), а второй - датой, когда произошло событие (на данный момент 31 отдельное значение, но увеличивается с каждым днем!).
Итак, при создании нашей новой таблицы мы выполнили такой запрос:
CREATE TABLE the_new_table
USING DELTA
PARTITIONED BY (entity_id, date)
AS SELECT
entity_id,
another_id,
from_unixtime(timestamp) AS timestamp,
CAST(from_unixtime(timestamp) AS DATE) AS date
FROM the_old_table
Этот запрос выполняется 48 часов и продолжает расти. Мы знаем, что он прогрессирует, потому что мы нашли около 250 тысяч префиксов, соответствующих первому ключу раздела в соответствующем префиксе S3, и, безусловно, в существующих префиксах есть несколько больших файлов.
Тем не менее, у нас возникают некоторые трудности с отслеживанием того, какой именно прогресс был достигнут и сколько времени мы можем ожидать для этого.
Пока мы ждали, мы попробовали такой запрос:
CREATE TABLE a_test_table (
entity_id STRING,
another_id STRING,
timestamp TIMESTAMP,
date DATE
)
USING DELTA
PARTITIONED BY (date);
INSERT INTO a_test_table
SELECT
entity_id,
another_id,
from_unixtime(timestamp) AS timestamp,
CAST(from_unixtime(timestamp) AS DATE) AS date
FROM the_old_table
WHERE CAST(from_unixtime(timestamp) AS DATE) = '2018-12-01'
Обратите внимание, что основное различие в схеме новой таблицы состоит в том, что мы секционировали только по дате, а не по идентификатору объекта. Выбранная нами дата содержит почти ровно четыре процента данных старой таблицы, на что я хочу обратить внимание, потому что это намного больше, чем 1/31. Конечно, поскольку мы выбираем по одному значению, которое оказывается тем же самым, что и мы разбили, мы фактически записываем только один раздел вместо, вероятно, сотни тысяч или около того.
Создание этой тестовой таблицы заняло 16 минут с использованием того же количества рабочих узлов, поэтому мы ожидаем (исходя из этого), что создание таблицы в 25 раз больше займет всего около 7 часов.
Этот ответ, похоже, частично подтверждает, что использование слишком большого количества разделов может вызвать проблему, но основные причины, по-видимому, сильно изменились в последние пару лет, поэтому мы стремимся понять, какие могут быть текущие проблемы; Databricks docs не особо проясняет ситуацию.
На основе опубликованных рекомендаций по скорости запросов для S3, похоже, увеличение количества разделов (префиксов ключей) должно улучшить производительность. Губительные перегородки кажутся нелогичными.
В итоге: мы ожидаем записать много тысяч записей в каждый из многих тысяч разделов. Похоже, что уменьшение количества разделов резко сокращает время, необходимое для записи данных таблицы. Почему это могло быть правдой? Существуют ли какие-либо общие рекомендации по количеству разделов, которые следует создавать для данных определенного размера?