Hive Join & SubQuery Урок с примери

⚡ Умно обобщение

Hive joins комбинира редове от две или повече таблици в съответстваща колона, а подзаявките влагат една заявка в друга, така че и двете са демонстрирани тук върху две примерни таблици, заредени от обикновени текстови файлове.

  • 🧱 Две примерни таблици: sample_joins съдържа данни за клиента, а sample_joins1 съдържа данни за поръчката, обединени в споделената колона Id.
  • 🔗 Четири вида съединяване: Вътрешните, левите външни, десните външни и пълните външни съединения поддържат различен набор от несъответстващи редове.
  • NULL маркира празнината: Външното съединение връща ред дори без съвпадение, запълвайки всяка колона от липсващата страна с NULL.
  • 🔁 Поръчката е важна: Съединенията не са комутативни и са ляво-асоциативни, така че размяната еping таблиците променят резултата от външно съединение.
  • 🧮 Подзаявки, вложени заявки: Подзаявката се записва в клаузата FROM или клаузата WHERE, а външната заявка зависи от стойността, която връща.
  • 📜 TRANSFORM вгражда скриптове: Персонализираните скриптове за map и reduce се изпълняват чрез клаузата TRANSFORM, когато няма вградена функция, която да пасва.

Примери за присъединяване към кошер и подзаявка

Присъединете се към заявки

Заявките за свързване могат да се изпълняват върху две таблици, присъстващи в КошерЗа да разберем ясно концепциите за съединение, създаваме две таблици тук:

  • sample_joins (свързани с данни за клиента)
  • sample_joins1 (свързано с подробности за поръчките, направени от служители)

Стъпка 1) Създаване на таблица „sample_joins“ с имената на колоните Id, Name, Age, address и salary на служителите. Снимката на екрана по-долу показва командата CREATE TABLE и нейното потвърждение.

Операторът Hive CREATE TABLE за таблицата клиенти sample_joins

Стъпка 2) Зареждане и показване на данни. Следващата екранна снимка показва командата за зареждане, последвана от съдържанието на таблицата.

Зареждане на Customers.txt в sample_joins и показване на заредените редове

От горната екранна снимка:

  1. Зареждане на данни в sample_joins от Customers.txt
  2. Показване на съдържанието на таблицата sample_joins

Стъпка 3) Създаване на таблицата sample_joins1, след което зареждане и показване на данните от нея, както е показано на екранната снимка по-долу.

Създаване на sample_joins1, зареждане на orders.txt и показване на редовете за поръчка

От горната екранна снимка можем да наблюдаваме следното:

  1. Създаване на таблица sample_joins1 с колоните Orderid, Date1, Id и Amount
  2. Зареждане на данни в sample_joins1 от orders.txt
  3. Показване на записи, налични в sample_joins1

В бъдеще ще видим различните видове съединения, които могат да се извършват върху таблиците, които сме създали. Преди това трябва да вземете предвид следните точки относно съединенията.

Някои точки, които трябва да се имат предвид при съединенията:

  • В съединенията са разрешени само съединения за равенство
  • Повече от две таблици могат да бъдат обединени в една и съща заявка
  • Съществуват LEFT, RIGHT и FULL OUTER съединения, за да осигурят по-голям контрол върху клаузата ON, за която няма съвпадение.
  • Съединенията не са комутативни
  • Съединенията са ляво-асоциативни, независимо дали са ЛЯВИ или ДЕСНИ съединения

Ограничението за равенство отразява Hive такъв, какъвто е бил в продължение на много години. От Hive 2.2.0 нататък, сложните изрази в клаузата ON се поддържат (HIVE-15211), така че условие за неравенство се приема в текущата версия. В по-старите версии условието трябва да бъде тест за равенство, като всичко останало се премества в клауза WHERE.

Различни видове присъединявания

Съединенията са от 4 вида. Те са:

  • Вътрешно присъединяване
  • Ляво външно съединение
  • Десен външен съединител
  • Пълно външно съединяване

Всеки тип е демонстриран по-долу спрямо едни и същи две таблици, така че единственото нещо, което се различава между примерите, е кои несъответстващи редове оцеляват.

Вътрешно присъединяване

Общите записи за двете таблици ще бъдат извлечени чрез това вътрешно съединение. Резултатът на екранната снимка по-долу съдържа само клиентите, които имат съответстваща поръчка.

Изход от вътрешното съединение на Hive, показващ само клиенти, които имат съответстваща поръчка

От горната екранна снимка можем да наблюдаваме следното:

  1. Тук изпълняваме заявка за съединение, използвайки ключовата дума JOIN между таблиците sample_joins и sample_joins1, с условието за съвпадение (c.Id = o.Id).
  2. Резултатът показва общите записи, присъстващи в двете таблици, избрани чрез проверка на условието, посочено в заявката.

Запитване:

SELECT c.Id, c.Name, c.Age, o.Amount FROM sample_joins c JOIN sample_joins1 o ON(c.Id=o.Id);

Ляво външно съединение

  • HiveQL LEFT OUTER JOIN връща всички редове от лявата таблица, въпреки че няма съвпадения в дясната таблица
  • Ако клаузата ON не съвпада с нула записи в дясната таблица, join-ът все пак връща запис в резултата с NULL във всяка колона от дясната таблица.

Екранната снимка по-долу показва, че се появяват всички клиенти, включително тези без поръчка.

Изход от ляво външно съединение на кошера с NULL стойности за клиенти без поръчки

От горната екранна снимка можем да наблюдаваме следното:

  1. Тук изпълняваме заявка за съединение, използвайки ключовата дума „LEFT OUTER JOIN“ между таблиците sample_joins и sample_joins1, с условие за съвпадение (c.Id = o.Id). Например, тук използваме идентификатора на служителя като отправна точка; проверява се дали идентификаторът е общ за дясната таблица, както и за лявата таблица. Той действа като условие за съвпадение.
  2. Резултатът показва записите, избрани от условието, посочено в заявката. NULL стойностите в горния резултат са колони без стойности от дясната таблица, т.е. sample_joins1.

Запитване:

SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c LEFT OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Дясно външно присъединяване

  • HiveQL RIGHT OUTER JOIN връща всички редове от дясната таблица, въпреки че няма съвпадения в лявата таблица
  • Ако клаузата ON не съвпада с нула записи в лявата таблица, join-ът все пак връща запис в резултата с NULL във всяка колона от лявата таблица.
  • RIGHT join-овете винаги връщат записи от дясната таблица и съответстващи записи от лявата таблица. Ако лявата таблица няма стойност, съответстваща на колоната, тя ще върне NULL стойности на това място.

Снимката на екрана по-долу показва огледален образ на предишния резултат: появява се всяка поръчка, независимо дали е съвпадаща или не.

Изходът на външното съединение на кошера отдясно keeping всеки ред от поръчката от sample_joins1

От горната екранна снимка можем да наблюдаваме следното:

  1. Тук изпълняваме заявка за съединение, използвайки ключовата дума „RIGHT OUTER JOIN“ между таблиците sample_joins и sample_joins1, с условието за съвпадение (c.Id = o.Id).
  2. Резултатът показва записите, избрани чрез проверка на условието, посочено в заявката.

Запитване:

  SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c RIGHT OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Пълно външно присъединяване

Той комбинира записите от таблиците sample_joins и sample_joins1 въз основа на условието JOIN, дадено в заявката.

Връща всички записи от двете таблици и попълва NULL стойности за колоните, чиито съответстващи стойности липсват от двете страни, както е показано на екранната снимка по-долу.

Изходът на Hive за пълно външно съединение, комбиниращ несъответстващи редове от двете таблици

От горната екранна снимка можем да наблюдаваме следното:

  1. Тук изпълняваме заявка за съединение, използвайки ключовата дума „FULL OUTER JOIN“ между таблиците sample_joins и sample_joins1, с условието за съвпадение (c.Id = o.Id).
  2. Резултатът показва всички записи, налични в двете таблици, избрани чрез проверка на условието, посочено в заявката. NULL стойностите в резултата тук показват липсващите стойности от колоните на двете таблици.

Запитване:

SELECT c.Id, c.Name, o.Amount, o.Date1 FROM sample_joins c FULL OUTER JOIN sample_joins1 o ON(c.Id=o.Id)

Подзапитвания

Съединенията поставят таблиците една до друга. Подзаявката прави нещо различно: тя влага една заявка в друга, така че външната заявка да може да работи с резултат, който вече е изчислен.

Заявка, присъстваща в заявка, се нарича подзаявка. Главната заявка ще зависи от стойностите, върнати от подзаявката.

Подзаявките могат да бъдат класифицирани в два вида:

  • Подзаявки в клаузата FROM
  • Подзаявки в клаузата WHERE

Кога да използвате:

  • За да получите конкретна стойност, комбинирана от две стойности на колони от различни таблици
  • Зависимост на стойностите на една таблица от други таблици
  • Сравнителна проверка на стойностите на една колона спрямо други таблици

Синтаксис:

Subquery in FROM clause
SELECT <column names 1, 2…n>From (SubQuery) <TableName_Main >
Subquery in WHERE clause
SELECT <column names 1, 2…n> From<TableName_Main>WHERE col1 IN (SubQuery);

Пример:

SELECT col1 FROM (SELECT a+b AS col1 FROM t1) t2

Тук t1 и t2 са имената на таблиците. Вътрешният оператор е подзаявката, изпълнена върху таблица t1. Тук a и b са колони, които се добавят в подзаявката и се присвояват на колона col1. Col1 е стойността на колоната, присъстваща в главната таблица. Тази колона „col1“, присъстваща в подзаявката, е еквивалентна на заявката към главната таблица в колона col1.

Вграждане на персонализирани скриптове

Докато подзаявка преоформя данните само с HiveQL, вграден скрипт предава редовете на код, написан извън Hive.

Hive позволява писането на специфични за потребителя скриптове за клиентски изисквания. Потребителите могат да пишат свои собствени map и reduce скриптове за тези изисквания. Те се наричат ​​вградени персонализирани скриптове. Логиката на кодиране е дефинирана в персонализирания скрипт и ние можем да използваме този скрипт по време на ETL.

Кога да изберете вградени скриптове:

  • Където специфичните за клиента изисквания означават, че разработчиците трябва да пишат и внедряват скриптове в Hive
  • Къде вградените функции на Hive няма да работят за специфични изисквания на домейна

За тази цел Hive използва клаузата TRANSFORM, за да вгради както map, така и reducer скриптове.

В тези вградени персонализирани скриптове трябва да спазваме следните точки:

  • Колоните ще бъдат трансформирани в низ и разделени с TAB, преди да бъдат предоставени на потребителския скрипт.
  • Стандартният изход на потребителския скрипт ще се третира като колони с низове, разделени с TAB.

Примерен вграден скрипт:

FROM (
	FROM pv_users
	MAP pv_users.userid, pv_users.date
	USING 'map_script'
	AS dt, uid
	CLUSTER BY dt) map_output

INSERT OVERWRITE TABLE pv_users_reduced
	REDUCE map_output.dt, map_output.uid
	USING 'reduce_script'
	AS date, count;

От горния скрипт можем да наблюдаваме следното. Това е само примерен скрипт за разбиране.

  • pv_users е таблицата с потребители, която съдържа полета като потребителско име и дата, както е посочено в map_script
  • Редукторният скрипт е дефиниран на базата на датата и броя на таблицата pv_users.

Въпроси и Отговори

Исторически не. От Hive 2.2.0 нататък сложните изрази са позволени в клаузата ON (HIVE-15211), така че условията за неравенство и диапазон работят. В по-ранни версии клаузата ON трябва да е тест за равенство, а всеки друг предикат принадлежи в WHERE.

Съединяването чрез карта зарежда по-малката таблица в паметта и пропуска изцяло етапа на редукция. Hive я избира автоматично, когато hive.auto.convert.join е true и таблицата отговаря на конфигурирания праг на размер, което прави съединенията от малка към голяма много по-бързи.

Връща редове от лявата таблица, които имат поне едно съвпадение отдясно, без да ги дублира и без да връща колони отдясно. Дясната таблица може да бъде посочена само в клаузата ON, а не в SELECT или WHERE.

Частично. От Hive 0.13 операторите IN, NOT IN, EXISTS и NOT EXISTS приемат подзаявки в клаузата WHERE, включително корелирани. Ограниченията остават, така че неподдържаната корелация обикновено се пренаписва като join.

Вътрешната заявка се превръща в производна таблица и всяка таблица се нуждае от име, преди да може да се прави препратка към нейните колони. Ето защо примерът завършва с t2 след затварящата скоба; пропускането на псевдонима води до грешка при синтактичен анализ.

Когато един ключ за свързване съдържа непропорционален дял от редове, един редуктор получава по-голямата част от работата, докато другите са бездействащи. Задаването на hive.optimize.skewjoin или разделянето на тежкия ключ и обединяването на резултатите разпределя натоварването.

Асистентите за машинно обучение прочитат плана EXPLAIN и маркират често срещани причини, като например липсващ филтър за дялове, неконвертирано съединение на карта или изкривен ключ. Разглеждайте предложението като отправна точка и го потвърждавайте спрямо плана и действителното време на изпълнение.

Той изготвя добре стандартни шаблони за присъединяване и подзаявки от кратък коментар. Проверете всичко специфично за търсачката, защото лесно се вписва Spark Синтаксис на SQL или Presto, а Hive отхвърля конструкции като неалиасирана производна таблица.

Обобщете тази публикация с: