Яка різниця між розділенням та групуванням таблиці в вулику?


129

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

Відповіді:


247

Розбиття даних часто використовується для розподілу навантаження по горизонталі, це має переваги в продуктивності, а також допомагає в організації даних в логічній формі. Приклад : якщо ми маємо справу з великою employeeтаблицею і часто запускаємо запити з WHEREпунктами, які обмежують результати в певній країні чи департаменті. Для швидшого відповіді на запит може бути таблиця вуликів 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
Спасибі Навнеет. Однак, чи можете ви пояснити, як відбувається взаємодія з розбиттям? Припустимо, якщо в пункті CLUSED BY буде вказано 32 відра, а вираз CREATE TABLE також містить застереження «Розбиття», як розділами та відрами керуватиме разом? Чи буде кількість розділів обмежена 32? АБО для кожної секції буде створено 32 відра? Чи кожне відро - це файл HDFS?
sgsi

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

7
@sgsi Розділ - це папка, відро - це файл.
зліва приєднується

12
Для запису ця відповідь випливає з тексту вулика програмування (O'Reilly, 2012).
ianmcook

1
Я вважаю це посилання корисним. У ньому є інформація, яка додасть більшої цінності цій відповіді. linkedin.com/pulse/…
Алекс Радж Каліаморті

129

У попередніх поясненнях бракує кількох деталей. Щоб краще зрозуміти, як працює розбиття та кодування, слід переглянути, як зберігаються дані у вулику. Скажімо, у вас є таблиця

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

Отже, ви повинні бути обережними при розділенні, тому що якщо ви, наприклад, розділ за службовим_идом і у вас мільйони співробітників, у вас в кінцевому рахунку буде мільйони каталогів у вашій файловій системі. Термін « кардинальність » означає кількість можливого значення, яке може мати поле. Наприклад, якщо у вас є поле "країна", країн у світі близько 300, тому кардинальність буде приблизно 300. Для такого типу, як "timestamp_ms", яке змінюється кожні мілісекунди, кардинальність може бути мільярдами. Взагалі, вибираючи поле для розділення, воно не повинно мати високу кардинальність, тому що ви отримаєте занадто багато каталогів у вашій файловій системі.

Згрупування ака-букетування з іншого боку, призведе до фіксованої кількості файлів, оскільки ви вказуєте кількість відра. Що буде робити вулик - це забрати поле, обчислити хеш і призначити запис цьому відрі. Але що станеться, якщо ви скажете 256 відро, і поле, яке ви використовуєте, має низьку кардинальність (наприклад, це штат США, тому може бути лише 50 різних значень)? У вас буде 50 відра з даними та 206 відра без даних.

Хтось уже згадував, як розділи можуть різко скоротити кількість запитуваних даних. Отже, у моєму прикладі таблиці, якщо ви хочете робити запит лише з певної дати вперед, розділення за роком / місяцем / днем ​​суттєво зменшить суму введення. Я думаю, що хтось також згадав про те, як bucketing може пришвидшити приєднання до інших таблиць, які мають точно таке ж здібнення , тому в моєму прикладі, якщо ви приєднуєте дві таблиці в одному і тому ж Employ_id , вулик може зробити відро для приєднання за відро (ще краще якщо вони вже відсортовані за службовим_идом, оскільки він збирається об'єднати вже впорядковані частини, що працює в лінійний час aka O (n)).

Таким чином, ковзання працює добре, коли поле має високу кардинальність і дані рівномірно розподіляються між собою. Розбиття найкраще працює, коли простота поля розділення не надто висока.

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


Чи можете ви пояснити, наприклад, поведінку CLUSTERED 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 не впливає.
Роберто Конгіу

Цікаво, я погоджуюся використовувати wrt у виборі запиту. Але цікавило, чому люди використовують кластеризовані та сортовані разом у операторі створення таблиць. Якщо SORTED BY не має значення в DDL, то чому це ключове слово присутнє? Не отримав це.
Ягадиш Таллурі

SORTED BY призначений для використання з DISTRIBUTED BY. Наприклад, ви можете розповсюдити ідентифікатор користувача та сортувати за часом у відрі. CLUSTER BY - це лише ярлик, коли пункт про SORTED BY і DISTRIBUTED BY однаковий. Єдине, про що я можу подумати - це якщо ви поширюєте по x, y і сортуєте по x, y і z
Роберто Конгіу

Я не впевнений, що ви маєте на увазі під "ви можете відро на лише одне поле". Я думаю, що можливо згрупувати декілька полів, функція хешування просто візьме всі поля та об'єднає їх.
Іштван

18

Я думаю, що я спізнююсь відповісти на це запитання, але це продовжує з'являтися в моєму каналі.

Навнеет дав чудову відповідь. Додавання до цього візуально.

Розмежування допомагає усунути дані, якщо вони використовуються в пункті WHERE, де як базування допомагає впорядковувати дані з кожного розділу в декілька файлів, так що один і той же набір даних завжди записується в одне відро. Дуже допомагає при з'єднанні стовпчиків.

Припустимо, у вас є таблиця з п'ятьма стовпцями, ім'ям, сервером_дані, деяким_колом3, деяким_кол4 та деяким_кол5. Припустимо, ви розділили таблицю на server_date і закрепили колонку з ім'ям у 10 відрах, ваша файлова структура буде виглядати приблизно як нижче.

  1. server_date = xyz
    • 00000_0
    • 00001_0
    • 00002_0
    • ........
    • 00010_0

Тут server_date = xyz - це розділ і 000 файлів - це відрізки у кожному розділі. Відра розраховуються виходячи з деяких хеш-функцій, тому рядки з ім'ям = Сенді завжди будуть в одному відрі.


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

server_date тут згадується як приклад. У реальному світі розділ зазвичай відбувається так, як зображено Роберто, шляхом розбиття дати на рік / місяць / день. Ось так і має бути.
Приєш

17

Розбиття вуликів:

Розділ розділяє велику кількість даних на кілька фрагментів на основі значення стовпців (таблиць).

Припустимо, що ви зберігаєте інформацію про людей у ​​всьому світі, розповсюджених у 196+ країнах, що охоплюють близько 500 крор. Якщо ви хочете запитувати людей з певної країни (Ватикан), за відсутності розділення вам потрібно сканувати всі 500 крор записів навіть для отримання тисяч записів країни. Якщо ви розділите таблицю на основі країни, ви можете впорядкувати процес запиту, просто перевіривши дані лише для одного розділу країни. Розділ вулика створює окремий каталог для значення стовпців (ив).

Плюси:

  1. Розподіліть навантаження на виконання горизонтально
  2. Швидше виконання запитів у разі розділу з малим обсягом даних. наприклад Отримати населення з міста Ватикану дуже швидко повертається замість того, щоб шукати все населення світу.

Мінуси:

  1. Можливість занадто багато невеликих творів розділів - занадто багато каталогів.
  2. Ефективно для даних з низьким обсягом для даного розділу. Але деякі запити, такі як групування за великим обсягом даних, все ще потребують тривалого часу. наприклад, Групування населення Китаю займе тривалий час порівняно з групуванням населення у Ватикані. Розділ не є вирішенням проблеми чутливості у випадку перекосу даних на певне значення розділу.

Будівництво вуликів:

Групування розбиває дані на більш керовані або рівні частини.

За допомогою розділення є можливість створення декількох невеликих розділів на основі значень стовпців. Якщо ви хочете скористатися, ви обмежуєте кількість відра для зберігання даних. Це число визначається під час створення сценаріїв таблиці.

Плюси

  1. Завдяки рівним обсягам даних у кожному розділі, приєднання на карті буде швидше.
  2. Швидше відповідь на запит, як розділення

Мінуси

  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що я згадував у розділі розділів. Це слід використовувати, коли в стовпчику є дуже мало повторюваних значень (приклад - стовпчик первинного ключа). Це схоже на концепцію індексу на стовпчику первинного ключа в RDBMS. У нашій таблиці ми можемо взяти 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()строку як функцію хеша? Чи може програміст вибрати хеш-функцію?
Дон Сміт

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

3

Різниця полягає в тому, що розбиття файлів ділить файли на ім’я стовпця, а розділення розділяє файли на За певним значенням всередині таблиці

Сподіваюся, я правильно це визначив


0

Тут чудові відгуки. Я хотів би, щоб це було коротше, щоб запам'ятати різницю між розділами та відрами.

Ви зазвичай розділяєте на менш унікальний стовпець. І гуртування на найбільш унікальній колонці.

Приклад, якщо ви розглядаєте населення світу з країною, ім'ям людини та їх біометричним ідентифікатором як приклад. Як ви здогадуєтесь, поле країни було б менш унікальним стовпцем, а біометричний ідентифікатор - самим унікальним стовпцем. Тож в ідеалі вам потрібно розділити таблицю за країною та згрупувати її за біометричним ідентифікатором.


-1

Використання розділів у таблиці вуликів настійно рекомендується з нижчих причин -

  • Вставка в таблицю вуликів повинна бути швидшою (оскільки для запису даних у розділи використовується декілька потоків)
  • Запит із таблиці Hive повинен бути ефективним із низькою затримкою.

Приклад: -

Припустимо, що вхідний файл (100 Гб) завантажується в таблицю temp-hive і містить банківські дані з різних географічних регіонів.

Вуличний стіл без перегородки

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.