Qual é a diferença entre particionar e agrupar uma tabela no Hive?

129

Eu sei que ambos são realizados em uma coluna na tabela, mas como cada operação é diferente.

NishM
fonte

Respostas:

247

Os dados de particionamento costumam ser usados ​​para distribuir a carga horizontalmente, isso traz benefícios de desempenho e ajuda na organização de dados de maneira lógica. Exemplo : se estamos lidando com uma employeetabela grande e geralmente executamos consultas com WHEREcláusulas que restringem os resultados a um país ou departamento específico. Para uma resposta mais rápida da consulta, a tabela Hive pode ser PARTITIONED BY (country STRING, DEPT STRING). As tabelas de particionamento alteram como o Hive estrutura o armazenamento de dados e o Hive agora cria subdiretórios que refletem a estrutura de particionamento, como

... / funcionários / país = ABC / DEPT = XYZ .

Se os limites de consulta para funcionários de country=ABC, ele verificará apenas o conteúdo de um diretório country=ABC. Isso pode melhorar drasticamente o desempenho da consulta, mas apenas se o esquema de particionamento refletir uma filtragem comum. O recurso de particionamento é muito útil no Hive, no entanto, um design que cria muitas partições pode otimizar algumas consultas, mas pode ser prejudicial para outras consultas importantes. Outra desvantagem é ter muitas partições: o grande número de arquivos e diretórios do Hadoop que são criados desnecessariamente e sobrecarga para o NameNode, pois ele deve manter todos os metadados do sistema de arquivos na memória.

O balde é outra técnica para decompor conjuntos de dados em partes mais gerenciáveis. Por exemplo, suponha que uma tabela usando datecomo partição de nível superior e employee_idcomo partição de segundo nível leve a muitas partições pequenas. Em vez disso, se juntarmos a tabela de funcionários e usarmos employee_idcomo a coluna de balde, o valor dessa coluna será dividido por hashes por um número definido pelo usuário em baldes. Os registros com o mesmo employee_id sempre serão armazenados no mesmo balde. Supondo que o número de employee_idseja muito maior que o número de buckets, cada bucket terá muitos employee_id. Ao criar a tabela, você pode especificar comoCLUSTERED BY (employee_id) INTO XX BUCKETS;onde XX é o número de baldes. O balde tem várias vantagens. O número de buckets é fixo para que não flutue com os dados. Se duas tabelas forem agrupadas employee_id, o Hive poderá criar uma amostra logicamente correta. O balde também ajuda a fazer junções eficientes no lado do mapa, etc.

Navneet Kumar
fonte
4
Obrigado Navneet. No entanto, você pode elaborar como o bucket acontece com o particionamento? Suponha que se especificarmos 32 buckets na cláusula CLUSED BY e a instrução CREATE TABLE também contiver a cláusula Partitioning, como as partições e os buckets serão gerenciados juntos? O número de partições será limitado a 32? OU para cada partição, serão criados 32 buckets? Todo depósito é um arquivo HDFS?
SGSI
12
Uma tabela de seção pode ter particionamento e bucket. Com base na sua cláusula de partição, para cada partição, serão criados 32 buckets. Sim arquivo HDFS.
Navneet Kumar 02/02
7
@sgsi Partition é uma pasta, bucket é um arquivo.
leftjoin
12
Para o registro, essa resposta deriva do texto de Programming Hive (O'Reilly, 2012).
Ianmcook 18/10/2016
1
Achei este link útil. Possui informações que agregam mais valor a essa resposta. linkedin.com/pulse/…
Alex Raj Kaliamoorthy
129

Faltam alguns detalhes nas explicações anteriores. Para entender melhor como funciona o particionamento e o bucket, verifique como os dados são armazenados no hive. Digamos que você tenha uma mesa

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

o hive armazenará dados em uma hierarquia de diretórios como

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

Portanto, você deve ter cuidado ao particionar, porque, por exemplo, se você particionar por employee_id e tiver milhões de funcionários, acabará tendo milhões de diretórios em seu sistema de arquivos. O termo ' cardinalidade ' refere-se ao número de valor possível que um campo pode ter. Por exemplo, se você tem um campo de 'país', os países do mundo são cerca de 300, portanto a cardinalidade seria ~ 300. Para um campo como 'timestamp_ms', que muda a cada milissegundo, a cardinalidade pode ser bilhões. Em geral, ao escolher um campo para particionamento, ele não deve ter uma alta cardinalidade, porque você acabará com muitos diretórios em seu sistema de arquivos.

O armazenamento em cluster, também conhecido como depósito, resultará em um número fixo de arquivos, pois você especifica o número de depósitos. O que a seção fará é entrar em campo, calcular um hash e atribuir um registro a esse balde. Mas o que acontece se você usar, digamos, 256 buckets e o campo em que está bucketed tiver uma cardinalidade baixa (por exemplo, é um estado dos EUA, então pode haver apenas 50 valores diferentes)? Você terá 50 depósitos com dados e 206 depósitos sem dados.

Alguém já mencionou como as partições podem reduzir drasticamente a quantidade de dados que você está consultando. Portanto, na minha tabela de exemplo, se você deseja consultar apenas a partir de uma determinada data, a partição por ano / mês / dia reduzirá drasticamente a quantidade de IO. Eu acho que alguém também mencionou como o bucketing pode acelerar junções com outras tabelas que têm exatamente o mesmo bucket , portanto, no meu exemplo, se você estiver juntando duas tabelas no mesmo employee_id, o hive poderá fazer o join bucket por bucket (ainda melhor se eles já estiverem classificados por employee_id, pois ele irá mesclar partes que já estão classificadas, o que funciona em tempo linear, também conhecido como O (n)).

Portanto, o depósito funciona bem quando o campo tem alta cardinalidade e os dados são distribuídos igualmente entre os depósitos. O particionamento funciona melhor quando a cardinalidade do campo de particionamento não é muito alta.

Além disso, é possível particionar em vários campos , com um pedido (ano / mês / dia é um bom exemplo), enquanto você pode agrupar apenas um campo .

Roberto Congiu
fonte
Você pode explicar o comportamento CLUSTERED-BY com SORTED-BY em um exemplo? Como no meu exemplo, achei SORTED-BY não fazendo nada. Estou faltando alguma coisa.
Jagadish Talluri
2
CLUSTERED BY x, y é como escrever DISTRIBUIR BY x, y CLASSIFICAR x, y (consulte cwiki.apache.org/confluence/display/Hive/… ), portanto, adicionar CLASSIFICAR a CLUSTERED BY não tem efeito.
Roberto Congiu 13/06/2016
Interessante, concordo com o uso na consulta de seleção. Mas se perguntou por que as pessoas estão usando clusterizadas e classificadas juntas na instrução de criação de tabela. Se não houver significado para SORTED BY no DDL, por que essa palavra-chave está presente? Não entendi isso.
Jagadish Talluri
SORTED BY deve ser usado com DISTRIBUTED BY. Por exemplo, você pode distribuir por ID do usuário e classificar por tempo dentro do bucket. CLUSTER BY é apenas um atalho para quando as cláusulas no SORTED BY e DISTRIBUTED BY são as mesmas. Única coisa que posso pensar é se você está distribuindo por x, y e classificação por x, y e z
Roberto Congiu
Não sei ao certo o que você quer dizer com "você pode encontrar apenas um campo". Eu acho que é possível fazer o bucket por vários campos, a função hash irá pegar todos os campos e combiná-los.
Istvan
18

Acho que estou atrasado em responder a essa pergunta, mas ela continua aparecendo no meu feed.

Navneet forneceu uma resposta excelente. Adicionando a ele visualmente.

O particionamento ajuda na eliminação de dados, se usado na cláusula WHERE, onde o bucket ajuda a organizar os dados em cada partição em vários arquivos, para que o mesmo conjunto de dados seja sempre gravado no mesmo bucket. Ajuda muito na junção de colunas.

Suponha que você tenha uma tabela com cinco colunas, nome, data_do_servidor, some_col3, some_col4 e some_col5. Suponha que você tenha particionado a tabela em server_date e agrupado a coluna de nome em 10 blocos, sua estrutura de arquivos será semelhante a abaixo.

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

Aqui server_date = xyz é a partição e 000 arquivos são os intervalos em cada partição. Os buckets são calculados com base em algumas funções de hash; portanto, as linhas com name = Sandy sempre estarão no mesmo bucket.

Priyesh
fonte
2
De acordo com Roberto na resposta acima, server_date seria um mau exemplo de particionamento, pois seu valor de cardinalidade é realmente alto. E assim você terá muitas pastas em hdfs.
Gaurang Shah 28/02
server_date é mencionado como um exemplo aqui. No mundo real, a partição geralmente acontece como representado por Roberto, dividindo a data em ano / mês / dia. É assim que deve ser.
Priyesh
17

Particionamento do Hive:

A partição divide grande quantidade de dados em várias fatias com base no valor de uma (s) coluna (s) da tabela.

Suponha que você esteja armazenando informações de pessoas em todo o mundo espalhadas por mais de 196 países, abrangendo cerca de 500 milhões de entradas. Se você deseja consultar pessoas de um país em particular (cidade do Vaticano), na ausência de particionamento, é necessário digitalizar todas as 500 crores de entradas, mesmo para buscar milhares de entradas de um país. Se você particionar a tabela com base no país, poderá ajustar o processo de consulta apenas verificando os dados de apenas uma partição de país. A partição Hive cria um diretório separado para um valor de coluna (s).

Prós:

  1. Distribuir carga de execução horizontalmente
  2. Execução mais rápida de consultas em caso de partição com baixo volume de dados. Por exemplo, obter a população da " cidade do Vaticano " retorna muito rápido, em vez de pesquisar em toda a população do mundo.

Contras:

  1. Possibilidade de muitas criações pequenas de partições - muitos diretórios.
  2. Eficaz para dados de baixo volume para uma determinada partição. Mas algumas consultas, como agrupar em alto volume de dados, ainda levam muito tempo para serem executadas. Por exemplo, o agrupamento da população da China levará muito tempo em comparação com o agrupamento da população na cidade do Vaticano. A partição não está resolvendo o problema de capacidade de resposta no caso de dados se inclinarem para um valor específico da partição.

Bucketing da colmeia:

O agrupamento decompõe os dados em partes mais gerenciáveis ​​ou iguais.

Com o particionamento, é possível criar várias pequenas partições com base nos valores da coluna. Se você for fazer o bucket, estará restringindo o número de buckets para armazenar os dados. Esse número é definido durante os scripts de criação de tabela.

Prós

  1. Devido aos volumes iguais de dados em cada partição, as junções no lado do Mapa serão mais rápidas.
  2. Resposta mais rápida à consulta, como particionamento

Contras

  1. Você pode definir o número de buckets durante a criação da tabela, mas o carregamento de igual volume de dados deve ser feito manualmente pelos programadores.
Ravindra babu
fonte
9

Antes de Bucketingentrarmos, precisamos entender o que Partitioningé. Vamos tomar a tabela abaixo como exemplo. Observe que forneci apenas 12 registros no exemplo abaixo para entender o nível iniciante. Em cenários em tempo real, você pode ter milhões de registros.

insira a descrição da imagem aqui



PARTITIONING
---------------------
Partitioning é usado para obter desempenho ao consultar os dados. Por exemplo, na tabela acima, se escrevermos o sql abaixo, ele precisará verificar todos os registros da tabela, o que reduz o desempenho e aumenta a sobrecarga.

select * from sales_table where product_id='P1'

Para evitar a varredura completa da tabela e ler apenas os registros relacionados product_id='P1', podemos particionar (dividir os arquivos da tabela da seção) em vários arquivos com base na product_idcoluna. Por isso, o arquivo da tabela de seção será dividido em dois arquivos, um com product_id='P1'e outro com product_id='P2'. Agora, quando executamos a consulta acima, ela examinará apenas o product_id='P1'arquivo.

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

A sintaxe para criar a partição é fornecida abaixo. Observe que não devemos usar a product_iddefinição de coluna junto com as colunas não particionadas na sintaxe abaixo. Isso deve estar apenas na partitioned bycláusula.

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

Contras : devemos ter muito cuidado ao particionar. Ou seja, não deve ser usado para as colunas em que o número de valores repetidos é muito menor (especialmente as colunas da chave primária), pois aumenta o número de arquivos particionados e aumenta a sobrecarga para o Name node.



BUCKETING
------------------
Bucketing é usado para superar o consque eu mencionei na seção de particionamento. Isso deve ser usado quando houver muito poucos valores repetidos em uma coluna (exemplo - coluna da chave primária). Isso é semelhante ao conceito de índice na coluna de chave primária no RDBMS. Em nossa tabela, podemos Sales_Idusar a coluna para o balde. Será útil quando precisarmos consultar a sales_idcoluna.

Abaixo está a sintaxe para o bucket.

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

Aqui, dividiremos ainda mais os dados em mais alguns arquivos sobre as partições.

insira a descrição da imagem aqui

Como especificamos os 3buckets, ele é dividido em três arquivos cada para cada um product_id. Ele usa internamente modulo operatorpara determinar em qual balde cada um sales_iddeve ser armazenado. Por exemplo, para o product_id='P1', o sales_id=1serão armazenados em 000001_0 arquivo (ou seja, 1% 3 = 1), sales_id=2será armazenado em 000002_0 ficheiro (isto é, 2% 3 = 2), sales_id=3será armazenado em 000000_0 ficheiro (isto é, 3% 3 = 0) etc.

Sarath Avanavu
fonte
Para colunas agrupadas numéricas, sempre é necessário mod pelo número de buckets? Para colunas em cluster com valor de sequência, ele usa o Java hashCode()da sequência como a função hash? O programador pode escolher a função hash?
Don Smith
Aparentemente (e de acordo com meus experimentos), o hive usa uma variação do método hashCode () de Java: github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/… . Isso foi mencionado aqui: stackoverflow.com/questions/30594038/… .
Don Smith
3

A diferença é que o bucket divide os arquivos por Nome da coluna e o particionamento divide os arquivos em Por um valor específico na tabela

Espero ter definido corretamente

uriya harel
fonte
0

Há ótimas respostas aqui. Gostaria de mantê-lo curto para memorizar a diferença entre partição e baldes.

Você geralmente particiona em uma coluna menos exclusiva. E balde na coluna mais exclusiva.

Exemplo se você considerar a população mundial com país, nome da pessoa e seu ID bio-métrico como exemplo. Como você pode imaginar, o campo do país seria a coluna menos exclusiva e o ID bio-métrico seria a coluna mais exclusiva. Idealmente, você precisaria particionar a tabela por país e agrupá-la pelo ID bio-métrico.

SVK
fonte
-1

O uso de Partições na tabela Hive é altamente recomendado pelo motivo abaixo -

  • A inserção na tabela Hive deve ser mais rápida (pois usa vários threads para gravar dados em partições)
  • A consulta da tabela Hive deve ser eficiente com baixa latência.

Exemplo: -

Suponha que o arquivo de entrada (100 GB) esteja carregado na tabela temp-hive e contenha dados bancários de diferentes geografias.

Tabela de colméia sem partição

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

O problema com esta abordagem é - Ele verificará os dados inteiros em busca de qualquer consulta que você executar nesta tabela. O tempo de resposta será alto se comparado a outras abordagens nas quais o particionamento e o bucket são usados.

Tabela de colméia com partição

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)

Prós - Aqui é possível acessar os dados mais rapidamente quando se trata de consultar dados para transações geográficas específicas. Contras - A inserção / consulta de dados pode ser melhorada dividindo-se os dados dentro de cada partição. Consulte a opção Bucketing abaixo.

Mesa de colméia com partição e caçamba

Nota: Crie tabela de seção ..... com "CLUSTERED BY (Partiton_Column) em 5 buckets

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)

Prós - inserção mais rápida. Consulta mais rápida.

Contras - O bucket irá criar mais arquivos. Pode haver um problema com muitos arquivos pequenos em alguns casos específicos

Espero que isso ajude !!

Ajay Ahuja
fonte