В чем разница между секционированием и сегментированием таблицы в Hive?


130

Я знаю, что обе операции выполняются в столбце таблицы, но чем отличается каждая операция.

Ответы:


248

Разделение данных часто используется для горизонтального распределения нагрузки, это дает преимущество в производительности и помогает в логической организации данных. Пример : если мы имеем дело с большой employeeтаблицей и часто выполняем запросы с WHEREпредложениями, которые ограничивают результаты определенной страной или отделом. Для более быстрого ответа на запрос таблица Hive может быть PARTITIONED BY (country STRING, DEPT STRING). Таблицы секционирования меняют структуру хранилища данных в Hive, и теперь Hive будет создавать подкаталоги, отражающие структуру секционирования, например

... / сотрудники / страна = ABC / DEPT = XYZ .

Если запрос ограничен для сотрудника из country=ABC, он будет сканировать только содержимое одного каталога country=ABC. Это может значительно повысить производительность запросов, но только если схема разделения отражает общую фильтрацию. Функция секционирования очень полезна в Hive, однако дизайн, который создает слишком много секций, может оптимизировать некоторые запросы, но быть вредным для других важных запросов. Другой недостаток - слишком много разделов - это большое количество файлов и каталогов Hadoop, которые создаются без необходимости, и накладные расходы для NameNode, поскольку он должен хранить все метаданные для файловой системы в памяти.

Группирование - это еще один метод разделения наборов данных на более управляемые части. Например, предположим, что таблица, используемая dateв качестве раздела верхнего уровня и раздела employee_idвторого уровня, приводит к слишком большому количеству небольших разделов. Вместо этого, если мы сгруппируем таблицу сотрудников и будем использовать ее employee_idв качестве столбца сегментирования, значение этого столбца будет хешироваться по заданному пользователем числу в сегменты. Записи с одинаковыми значениями employee_id всегда будут храниться в одной корзине. Предполагая, что количество employee_idнамного больше, чем количество сегментов, в каждом сегменте будет их много employee_id. При создании таблицы вы можете указать какCLUSTERED BY (employee_id) INTO XX BUCKETS;где XX - количество ведер. Ковширование имеет несколько преимуществ. Количество сегментов фиксировано, поэтому оно не зависит от данных. Если две таблицы разделены employee_id, Hive может создать логически правильную выборку. Группирование также помогает в выполнении эффективных соединений на стороне карты и т. Д.


4
Спасибо Navneet. Однако можете ли вы уточнить, как ведется сегментирование при разделении? Предположим, что если мы укажем 32 сегмента в предложении CLUSED BY, а оператор CREATE TABLE также будет содержать предложение Partitioning, как разделы и сегменты будут управляться вместе? Будет ли количество разделов ограничено 32? ИЛИ для каждого раздела будет создано 32 ведра? Каждая корзина - это файл HDFS?
sgsi 02 фев.15,

12
Таблица-улей может иметь как разделы, так и сегменты. В соответствии с вашим предложением о разделах для каждого раздела будет создано 32 сегмента. Да файл HDFS.
Навнит Кумар

7
@sgsi Partition - это папка, bucket - это файл.
leftjoin 01

12
Для справки, этот ответ взят из текста книги Programming Hive (O'Reilly, 2012).
ianmcook

1
Я нашел эту ссылку полезной. В нем есть информация, которая повысит ценность этого ответа. linkedin.com/pulse/…
Alex Raj Kaliamoorthy

130

В предыдущих объяснениях отсутствуют некоторые детали. Чтобы лучше понять, как работает разделение и сегментирование, вы должны посмотреть, как данные хранятся в кусте. Допустим, у вас есть стол

CREATE TABLE mytable ( 
         name string,
         city string,
         employee_id int ) 
PARTITIONED BY (year STRING, month STRING, day STRING) 
CLUSTERED BY (employee_id) INTO 256 BUCKETS

тогда улей будет хранить данные в иерархии каталогов, например

/user/hive/warehouse/mytable/y=2015/m=12/d=02

Итак, вы должны быть осторожны при разделении, потому что, если вы, например, разделите по employee_id и у вас есть миллионы сотрудников, в вашей файловой системе будут миллионы каталогов. Термин « мощность » относится к числу возможных значений поля может иметь. Например, если у вас есть поле «страна», стран в мире около 300, поэтому количество элементов будет ~ 300. Для поля типа «timestamp_ms», которое изменяется каждую миллисекунду, количество элементов может составлять миллиарды. В общем, при выборе поля для разделения оно не должно иметь большого количества элементов, потому что в результате в вашей файловой системе будет слишком много каталогов.

С другой стороны, кластеризация, также известная как сегментирование, приведет к фиксированному количеству файлов, поскольку вы указываете количество сегментов. Что улей будет делать, так это брать поле, вычислять хэш и назначать запись этому ведру. Но что произойдет, если вы используете, скажем, 256 сегментов, а поле, в котором вы ведете сегмент, имеет низкую мощность (например, это штат США, поэтому может быть только 50 различных значений)? У вас будет 50 сегментов с данными и 206 сегментов без данных.

Кто-то уже упоминал, как разделы могут значительно сократить объем запрашиваемых данных. Итак, в моем примере таблицы, если вы хотите запрашивать только с определенной даты вперед, разделение по годам / месяцам / дням значительно сократит количество операций ввода-вывода. Я думаю, что кто-то также упомянул, как сегментирование может ускорить объединение с другими таблицами, которые имеют точно такое же сегментирование , поэтому в моем примере, если вы объединяете две таблицы с одним и тем же идентификатором employee_id, улей может выполнять объединение ведро за ведром (даже лучше если они уже отсортированы по employee_id, так как он собирается объединить части, которые уже отсортированы, что работает в линейном времени, также известном как O (n)).

Таким образом, сегментирование хорошо работает, когда поле имеет высокую мощность и данные равномерно распределены по сегментам. Разделение работает лучше всего, когда мощность поля разделения не слишком велика.

Кроме того, вы можете разделить на несколько полей в порядке (год / месяц / день - хороший пример), в то время как вы можете сегментировать только одно поле .


Не могли бы вы объяснить поведение CLUSTERED-BY с помощью SORTED-BY на примере? В моем примере я обнаружил, что SORTED-BY ничего не делает. Я что-нибудь упускаю?
Джагадиш Таллури

2
CLUSTERED BY x, y похож на запись DISTRIBUTE BY x, y SORT BY x, y (см. Cwiki.apache.org/confluence/display/Hive/… ), поэтому добавление SORT BY к CLUSTERED BY не имеет никакого эффекта.
Роберто Конгиу

Интересно, что я согласен с использованием в запросе выбора. Но задался вопросом, почему люди используют кластеризацию и сортировку вместе в операторе создания таблицы. Если в DDL нет значения для SORTED BY, то почему это ключевое слово присутствует? Не понял.
Джагадиш Таллури

SORTED BY предназначен для использования с DISTRIBUTED BY. Например, вы можете захотеть распределить по идентификатору пользователя и отсортировать по времени внутри корзины. CLUSTER BY - это просто ярлык для случаев, когда предложения в SORTED BY и DISTRIBUTED BY совпадают. Единственное, о чем я могу думать, это если вы распределяете по x, y и сортируете по x, y и z
Роберто Конгиу

Я не понимаю, что вы имеете в виду под «ведром только на одном поле». Я думаю, что можно сгруппировать по нескольким полям, функция хеширования просто возьмет все поля и объединит их.
Istvan

18

Я думаю, что опаздываю с ответом на этот вопрос, но он продолжает появляться в моей ленте.

Navneet дал отличный ответ. Добавляем к нему визуально.

Разделение помогает в удалении данных, если оно используется в предложении WHERE, где сегментирование помогает организовать данные в каждом разделе в несколько файлов, так как один и тот же набор данных всегда записывается в одном сегменте. Очень помогает при соединении столбцов.

Предположим, у вас есть таблица с пятью столбцами: name, server_date, some_col3, some_col4 и some_col5. Предположим, вы разбили таблицу на server_date и разбили столбец имени на 10 сегментов, ваша файловая структура будет выглядеть примерно так, как показано ниже.

  1. server_date = хуг
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0

Здесь server_date = xyz - это раздел, а 000 файлов - это сегменты в каждом разделе. Сегменты рассчитываются на основе некоторых хэш-функций, поэтому строки с именем = Sandy всегда будут находиться в одном сегменте.


2
Согласно Роберто в приведенном выше ответе server_date был бы плохим примером для выполнения разделения, поскольку его значение мощности действительно велико. И в результате у вас будет слишком много папок в hdfs.
Гауранг Шах

server_date упоминается здесь в качестве примера. В реальном мире разделение обычно происходит так, как показано Роберто, путем разбивки даты на год / месяц / день. Так и должно быть.
Priyesh

17

Разбиение улья:

Разделение делит большой объем данных на несколько срезов в зависимости от значения столбца (столбцов) таблицы.

Предположим, вы храните информацию о людях со всего мира, разбросанных по более чем 196 странам, с охватом около 500 крор записей. Если вы хотите запросить людей из определенной страны (города Ватикана), при отсутствии разделения вам нужно отсканировать все 500 крор записей, даже чтобы получить тысячи записей о стране. Если вы разбиваете таблицу по странам, вы можете точно настроить процесс запросов, просто проверив данные только для одного раздела страны. Раздел Hive создает отдельный каталог для значений столбцов.

Плюсы:

  1. Распределить нагрузку на выполнение по горизонтали
  2. Более быстрое выполнение запросов в случае раздела с небольшим объемом данных. например, Получить население из " Ватикана " возвращается очень быстро вместо поиска всего населения мира.

Минусы:

  1. Возможность создания слишком большого количества небольших разделов - слишком много каталогов.
  2. Эффективно для данных небольшого объема для данного раздела. Но выполнение некоторых запросов, таких как группировка по большому объему данных, по-прежнему занимает много времени. например, группировка населения Китая займет много времени по сравнению с группировкой населения в Ватикане. Разделение не решает проблему отзывчивости в случае смещения данных в сторону определенного значения раздела.

Ковширование улья:

При сегментации данные разбиваются на более управляемые или равные части.

При разбиении на разделы можно создать несколько небольших разделов на основе значений столбцов. Если вы выбираете сегментирование, вы ограничиваете количество сегментов для хранения данных. Это число определяется в скриптах создания таблиц.

Pros

  1. Благодаря равным объемам данных в каждом разделе соединения на стороне карты будут быстрее.
  2. Более быстрый ответ на запрос, например, секционирование

Cons

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

9

Прежде чем углубляться Bucketing, нам нужно понять, что это Partitioningтакое. В качестве примера возьмем приведенную ниже таблицу. Обратите внимание, что в приведенном ниже примере я привел только 12 записей для понимания начального уровня. В сценариях реального времени у вас могут быть миллионы записей.

введите описание изображения здесь



РАЗДЕЛЕНИЕ
---------------------
Partitioning используется для получения производительности при запросе данных. Например, в приведенной выше таблице, если мы напишем приведенный ниже sql, ему необходимо просканировать все записи в таблице, что снижает производительность и увеличивает накладные расходы.

select * from sales_table where product_id='P1'

Чтобы избежать полного сканирования таблицы и читать только относящиеся к ним записи, product_id='P1'мы можем разделить (разбить файлы таблицы куста) на несколько файлов на основе product_idстолбца. Таким образом, файл таблицы улья будет разделен на два файла, один с, product_id='P1'а другой с product_id='P2'. Теперь, когда мы выполняем вышеуказанный запрос, он будет сканировать только product_id='P1'файл.

../hive/warehouse/sales_table/product_id=P1
../hive/warehouse/sales_table/product_id=P2

Синтаксис создания раздела приведен ниже. Обратите внимание, что мы не должны использовать product_idопределение столбца вместе с несекционированными столбцами в синтаксисе ниже. Это должно быть только в partitioned byпункте.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10))

Минусы : мы должны быть очень осторожны при разметке. То есть его не следует использовать для столбцов, в которых количество повторяющихся значений очень мало (особенно столбцов с первичным ключом), поскольку это увеличивает количество секционированных файлов и увеличивает накладные расходы для Name node.



BUCKETING
------------------
Bucketing используется для преодоления того, consчто я упоминал в разделе о разделах. Это следует использовать, когда в столбце очень мало повторяющихся значений (пример - столбец первичного ключа). Это похоже на концепцию индекса по столбцу первичного ключа в СУБД. В нашей таблице мы можем взять Sales_Idстолбец для сегментирования. Это будет полезно, когда нам нужно запросить sales_idстолбец.

Ниже приведен синтаксис сегментации.

create table sales_table(sales_id int,trans_date date, amount int) 
partitioned by (product_id varchar(10)) Clustered by(Sales_Id) into 3 buckets

Здесь мы дополнительно разделим данные на несколько файлов поверх разделов.

введите описание изображения здесь

Поскольку мы указали 3сегменты, каждый из них разделен на 3 файла product_id. Он внутренне использует, modulo operatorчтобы определить, в каком ведре sales_idследует хранить каждый из них. Например, для product_id='P1', то sales_id=1будет храниться в 000001_0 файла (т.е. 1% 3 = 1), sales_id=2будет храниться в 000002_0 файле (то есть, 2% 3 = 2), sales_id=3будет храниться в 000000_0 файле (т.е. 3% 3 = 0) и т. Д.


Всегда ли для числовых кластеризованных столбцов используется модификация только по количеству сегментов? Для кластеризованных столбцов со строковым значением используется ли Java hashCode()строки в качестве хеш-функции? Может ли программист выбрать хеш-функцию?
Дон Смит

По-видимому (и в соответствии с моими экспериментами) улей использует вариант метода Java hashCode (): github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/… . Об этом упоминалось здесь: stackoverflow.com/questions/30594038/… .
Дон Смит

3

Разница в том, что сегментирование разделяет файлы по имени столбца, а разделение разделяет файлы по определенному значению внутри таблицы.

Надеюсь, я правильно определил


0

Здесь есть отличные отзывы. Я хотел бы сделать его кратким, чтобы запомнить разницу между разделами и корзинами.

Обычно вы разбиваете на менее уникальный столбец. И ведро по самой уникальной колонке.

Пример, если вы рассматриваете население мира с указанием страны, имени человека и его биометрического идентификатора в качестве примера. Как вы можете догадаться, поле страны будет менее уникальным столбцом, а биометрический идентификатор будет наиболее уникальным столбцом. Поэтому в идеале вам нужно разделить таблицу по странам и разделить ее по биометрическому идентификатору.


-1

Использование разделов в таблице Hive настоятельно рекомендуется по следующей причине:

  • Вставка в таблицу Hive должна быть быстрее (поскольку она использует несколько потоков для записи данных в разделы)
  • Запрос из таблицы Hive должен быть эффективным с малой задержкой.

Пример :-

Предположим, что входной файл (100 ГБ) загружен в таблицу temp-hive-table и содержит банковские данные из разных географических регионов.

Таблица улья без перегородки

Insert into Hive table Select * from temp-hive-table

/hive-table-path/part-00000-1  (part size ~ hdfs block size)
/hive-table-path/part-00000-2
....
/hive-table-path/part-00000-n

Проблема с этим подходом заключается в том, что он будет сканировать все данные для любого запроса, который вы запускаете в этой таблице. Время отклика будет большим по сравнению с другими подходами, в которых используются разделы и сегментирование.

Таблица улья с перегородкой

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 10 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 20 GB)
....
/hive-table-path/country=UK/part-00000-n       (file size ~ 5 GB)

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

Стол-улей с перегородками и ведрами

Примечание. Создайте таблицу улья ..... с "CLUSTERED BY (Partiton_Column) в 5 сегментов"

Insert into Hive table partition(country) Select * from temp-hive-table

/hive-table-path/country=US/part-00000-1       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-2       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-3       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-4       (file size ~ 2 GB)
/hive-table-path/country=US/part-00000-5       (file size ~ 2 GB)

/hive-table-path/country=Canada/part-00000-1   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-2   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-3   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-4   (file size ~ 4 GB)
/hive-table-path/country=Canada/part-00000-5   (file size ~ 4 GB)

....
/hive-table-path/country=UK/part-00000-1       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-2       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-3       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-4       (file size ~ 1 GB)
/hive-table-path/country=UK/part-00000-5       (file size ~ 1 GB)

Плюсы - Быстрая вставка. Более быстрый запрос.

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

Надеюсь, это поможет !!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.