Apa perbedaan antara mempartisi dan men-ember tabel di Hive?

129

Saya tahu keduanya dilakukan pada kolom di tabel tetapi bagaimana setiap operasi berbeda.

NishM
sumber

Jawaban:

247

Partisi data sering digunakan untuk mendistribusikan beban secara horizontal, ini memiliki manfaat kinerja, dan membantu dalam mengatur data secara logis. Contoh : jika kita berhadapan dengan employeetabel besar dan sering menjalankan kueri dengan WHEREklausa yang membatasi hasil untuk negara atau departemen tertentu. Untuk respons kueri yang lebih cepat, tabel Hive dapat dibuat PARTITIONED BY (country STRING, DEPT STRING). Tabel partisi mengubah bagaimana Hive struktur penyimpanan data dan Hive sekarang akan membuat subdirektori yang mencerminkan struktur partisi seperti

... / karyawan / negara = ABC / DEPT = XYZ .

Jika batasan kueri untuk karyawan dari country=ABC, itu hanya akan memindai konten dari satu direktori country=ABC. Ini secara dramatis dapat meningkatkan kinerja kueri, tetapi hanya jika skema partisi mencerminkan pemfilteran umum. Fitur pemartisian sangat berguna di Hive, namun, desain yang membuat terlalu banyak partisi dapat mengoptimalkan beberapa kueri, tetapi akan mengganggu kueri penting lainnya. Kelemahan lainnya adalah terlalu banyak partisi adalah banyaknya file dan direktori Hadoop yang dibuat tidak perlu dan overhead ke NameNode karena harus menyimpan semua metadata untuk sistem file dalam memori.

Bucketing adalah teknik lain untuk mendekomposisi set data menjadi bagian yang lebih mudah dikelola. Sebagai contoh, anggaplah sebuah tabel menggunakan datesebagai partisi tingkat atas dan employee_idsebagai partisi tingkat kedua menyebabkan terlalu banyak partisi kecil. Alih-alih, jika kita mengaitkan tabel karyawan dan digunakan employee_idsebagai kolom penimbunan, nilai kolom ini akan di-hash dengan angka yang ditentukan pengguna menjadi ember. Catatan dengan hal yang sama employee_id akan selalu disimpan dalam ember yang sama. Dengan asumsi jumlah employee_idjauh lebih besar daripada jumlah ember, setiap ember akan memiliki banyak employee_id. Saat membuat tabel Anda dapat menentukan sukaCLUSTERED BY (employee_id) INTO XX BUCKETS;di mana XX adalah jumlah ember. Bucketing memiliki beberapa keunggulan. Jumlah bucket diperbaiki sehingga tidak berfluktuasi dengan data. Jika dua tabel diatasi oleh employee_id, Hive dapat membuat pengambilan sampel yang benar secara logis. Memberi ember juga membantu dalam melakukan penggabungan sisi-peta yang efisien, dll.

Navneet Kumar
sumber
4
Terima kasih Navneet. Namun, dapatkah Anda menguraikan bagaimana bucketing terjadi dengan pemartisian? Misalkan jika kita menentukan 32 bucket dalam klausa CLUSED BY dan pernyataan CREATE TABLE juga berisi klausa Partitioning, bagaimana partisi dan bucket dikelola bersama? Apakah jumlah partisi akan dibatasi hingga 32? ATAU untuk setiap partisi, 32 ember akan dibuat? Apakah setiap ember adalah file HDFS?
sgsi
12
Tabel sarang dapat memiliki partisi dan bucket. Berdasarkan klausa partisi Anda, untuk setiap partisi akan dibuat 32 ember. Ya file HDFS.
Navneet Kumar
7
@sgsi Partisi adalah folder, ember adalah file.
leftjoin
12
Sebagai catatan, jawaban ini berasal dari teks Programming Hive (O'Reilly, 2012).
ianmcook
1
Saya menemukan tautan ini bermanfaat. Ini memiliki informasi yang akan menambah nilai pada jawaban ini. linkedin.com/pulse/…
Alex Raj Kaliamoorthy
129

Ada beberapa detail yang hilang dari penjelasan sebelumnya. Untuk lebih memahami cara kerja partisi dan bucket, Anda harus melihat bagaimana data disimpan di sarang. Katakanlah Anda punya meja

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

maka sarang akan menyimpan data dalam hirarki direktori seperti

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

Jadi, Anda harus berhati-hati ketika mempartisi, karena jika Anda misalnya mempartisi oleh employee_id dan Anda memiliki jutaan karyawan, Anda akan memiliki jutaan direktori di sistem file Anda. Istilah ' kardinalitas ' mengacu pada jumlah nilai yang mungkin dimiliki suatu bidang. Misalnya, jika Anda memiliki bidang 'negara', negara-negara di dunia adalah sekitar 300, jadi kardinalitas akan ~ 300. Untuk bidang seperti 'timestamp_ms', yang berubah setiap milidetik, kardinalitas bisa miliaran. Secara umum, ketika memilih bidang untuk dipartisi, seharusnya tidak memiliki kardinalitas tinggi, karena Anda akan berakhir dengan direktori terlalu banyak dalam sistem file Anda.

Clustering alias bucketing di sisi lain, akan menghasilkan jumlah file yang tetap, karena Anda menentukan jumlah bucket. Apa sarang akan lakukan adalah untuk mengambil bidang, menghitung hash dan menetapkan catatan ke ember itu. Tetapi apa yang terjadi jika Anda menggunakan katakanlah 256 ember dan bidang yang Anda tangani memiliki kardinalitas rendah (misalnya, ini adalah negara bagian AS, jadi hanya 50 nilai yang berbeda)? Anda akan memiliki 50 ember dengan data, dan 206 ember tanpa data.

Seseorang telah menyebutkan bagaimana partisi dapat secara dramatis memotong jumlah data yang Anda tanyakan. Jadi, dalam tabel contoh saya, jika Anda ingin melakukan kueri hanya dari tanggal tertentu ke depan, partisi berdasarkan tahun / bulan / hari akan secara dramatis memotong jumlah IO. Saya pikir seseorang juga menyebutkan bagaimana bucket dapat mempercepat penggabungan dengan tabel lain yang memiliki bucket yang sama persis , jadi dalam contoh saya, jika Anda bergabung dengan dua tabel pada employee_id yang sama, sarang dapat melakukan gabungan bucket dengan bucket (bahkan lebih baik jika mereka sudah diurutkan berdasarkan employee_id karena akan menggabungkan bagian-bagian yang sudah diurutkan, yang bekerja dalam waktu linier alias O (n)).

Jadi, bucket bekerja dengan baik ketika bidang memiliki kardinalitas tinggi dan data didistribusikan secara merata di antara bucket. Partisi berfungsi paling baik ketika kardinalitas bidang partisi tidak terlalu tinggi.

Selain itu, Anda dapat mempartisi pada beberapa bidang , dengan pesanan (tahun / bulan / hari adalah contoh yang baik), sementara Anda hanya dapat melakukan bucket pada satu bidang .

Roberto Congiu
sumber
Bisakah Anda jelaskan perilaku CLUSTERED-BY dengan SORTED-BY dalam contoh? Sesuai contoh saya, saya menemukan SORTED-BY tidak melakukan apa-apa. Apakah saya kehilangan sesuatu?
Jagadish Talluri
2
DITAMPILKAN OLEH x, y seperti menulis DISTRIBUT OLEH x, y SORT OLEH x, y (lihat cwiki.apache.org/confluence/display/Hive/… ) sehingga menambahkan SORT BY ke CLUSTERED BY tidak berpengaruh.
Roberto Congiu
Menarik, saya setuju dengan penggunaan dalam kueri pemilihan. Tapi bertanya-tanya mengapa orang menggunakan dikelompokkan dan diurutkan bersama dalam pernyataan pembuatan tabel. Jika tidak ada arti penting SORTED BY di DDL, lalu mengapa kata kunci ini ada? Tidak mengerti.
Jagadish Talluri
DILIHAT OLEH dimaksudkan untuk digunakan dengan OLEH DISTRIBUSI OLEH. Misalnya, Anda mungkin ingin didistribusikan berdasarkan id pengguna dan mengurutkan berdasarkan waktu dalam ember. CLUSTER BY hanyalah jalan pintas ketika klausa pada SORTED BY dan DISTRIBUTED BY adalah sama. Satu-satunya hal yang dapat saya pikirkan adalah jika Anda mendistribusikan dengan x, y dan mengurutkan berdasarkan x, y dan z
Roberto Congiu
Saya tidak yakin apa yang Anda maksud dengan "Anda hanya dapat melakukan bucket pada satu bidang." Saya pikir ini mungkin untuk ember dengan beberapa bidang fungsi hashing hanya akan mengambil semua bidang dan menggabungkannya.
Istvan
18

Saya pikir saya terlambat menjawab pertanyaan ini, tetapi terus muncul di feed saya.

Navneet telah memberikan jawaban yang sangat bagus. Menambahkannya secara visual.

Partisi membantu dalam penghapusan data, jika digunakan dalam klausa WHERE, sedangkan bucket membantu dalam mengatur data di setiap partisi menjadi beberapa file, sehingga kumpulan data yang sama selalu ditulis dalam ember yang sama. Banyak membantu dalam menggabungkan kolom.

Misalkan, Anda memiliki tabel dengan lima kolom, nama, server_date, some_col3, some_col4 dan some_col5. Misalkan, Anda telah mempartisi tabel pada server_date dan di- bucket pada kolom nama dalam 10 ember, struktur file Anda akan terlihat seperti di bawah ini.

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

Di sini server_date = xyz adalah partisi dan 000 file adalah ember di setiap partisi. Bucket dihitung berdasarkan beberapa fungsi hash, jadi baris dengan nama = Sandy akan selalu masuk dalam bucket yang sama.

Priyesh
sumber
2
Menurut Roberto dalam jawaban di atas server_date akan menjadi contoh yang buruk untuk melakukan partisi karena nilai kardinalitasnya sangat tinggi. Dan akhirnya Anda akan memiliki terlalu banyak folder dalam hdfs.
Gaurang Shah
server_date disebutkan sebagai contoh di sini. Di dunia nyata, partisi umumnya terjadi seperti yang digambarkan oleh Roberto, dengan memecah tanggal menjadi tahun / bulan / hari. Begitulah seharusnya.
Priyesh
17

Sarang Partisi:

Partisi membagi sejumlah besar data menjadi beberapa irisan berdasarkan nilai kolom tabel.

Asumsikan bahwa Anda menyimpan informasi orang-orang di seluruh dunia yang tersebar di 196+ negara yang mencakup sekitar 500 crores entri. Jika Anda ingin meminta orang dari negara tertentu (kota Vatikan), jika tidak ada partisi, Anda harus memindai semua 500 crores entri bahkan untuk mengambil ribuan entri dari suatu negara. Jika Anda mempartisi tabel berdasarkan negara, Anda dapat mengatur proses kueri hanya dengan memeriksa data hanya satu partisi negara. Partisi sarang membuat direktori terpisah untuk nilai kolom.

Pro:

  1. Mendistribusikan beban eksekusi secara horizontal
  2. Eksekusi query lebih cepat jika terjadi partisi dengan volume data yang rendah. mis. Dapatkan populasi dari " kota Vatikan " kembali dengan sangat cepat alih-alih mencari seluruh populasi dunia.

Cons:

  1. Kemungkinan terlalu banyak kreasi partisi kecil - terlalu banyak direktori.
  2. Efektif untuk data volume rendah untuk partisi yang diberikan. Tetapi beberapa pertanyaan seperti grup dengan volume data yang tinggi masih membutuhkan waktu lama untuk dieksekusi. mis. Pengelompokan populasi Cina akan memakan waktu lama dibandingkan dengan pengelompokan populasi di kota Vatikan. Partisi tidak memecahkan masalah responsif jika data condong ke nilai partisi tertentu.

Sarang Bucketing:

Bucket menguraikan data menjadi bagian yang lebih mudah dikelola atau sama.

Dengan mempartisi, ada kemungkinan Anda bisa membuat banyak partisi kecil berdasarkan nilai kolom. Jika Anda menggunakan bucket, Anda membatasi jumlah bucket untuk menyimpan data. Angka ini didefinisikan selama skrip pembuatan tabel.

Pro

  1. Karena volume data yang sama di setiap partisi, bergabung di sisi Peta akan lebih cepat.
  2. Respons kueri yang lebih cepat seperti mempartisi

Cons

  1. Anda dapat menentukan jumlah bucket selama pembuatan tabel tetapi memuat volume data yang sama harus dilakukan secara manual oleh programmer.
Ravindra babu
sumber
9

Sebelum masuk Bucketing, kita perlu memahami apa Partitioningitu. Mari kita ambil tabel di bawah ini sebagai contoh. Perhatikan bahwa saya hanya memberikan 12 catatan dalam contoh di bawah ini untuk pemahaman tingkat pemula. Dalam skenario real-time Anda mungkin memiliki jutaan catatan.

masukkan deskripsi gambar di sini



PARTITIONING
---------------------
Partitioning digunakan untuk mendapatkan kinerja saat meminta data. Misalnya, dalam tabel di atas, jika kita menulis sql di bawah ini, perlu memindai semua catatan di tabel yang mengurangi kinerja dan meningkatkan overhead.

select * from sales_table where product_id='P1'

Untuk menghindari pemindaian tabel penuh dan hanya membaca catatan yang terkait dengan product_id='P1'kita dapat mempartisi (membagi file tabel sarang) menjadi beberapa file berdasarkan product_idkolom. Dengan ini file tabel sarang akan dibagi menjadi dua file satu dengan product_id='P1'dan lainnya dengan product_id='P2'. Sekarang ketika kita menjalankan query di atas, itu hanya akan memindai product_id='P1'file.

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

Sintaks untuk membuat partisi diberikan di bawah ini. Perhatikan bahwa kita tidak boleh menggunakan product_iddefinisi kolom bersama dengan kolom yang tidak dipartisi dalam sintaksis di bawah ini. Ini seharusnya hanya dalam partitioned byklausa.

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

Cons : Kita harus sangat berhati-hati saat mempartisi. Artinya, itu tidak boleh digunakan untuk kolom di mana jumlah nilai berulang sangat kurang (terutama kolom kunci utama) karena meningkatkan jumlah file yang dipartisi dan meningkatkan overhead untuk Name node.



BUCKETING
------------------
Bucketing digunakan untuk mengatasi consyang saya sebutkan di bagian partisi. Ini harus digunakan ketika ada sangat sedikit nilai yang berulang dalam kolom (contoh - kolom kunci utama). Ini mirip dengan konsep indeks pada kolom kunci utama dalam RDBMS. Di meja kami, kami dapat mengambil Sales_Idkolom untuk disemen. Ini akan berguna ketika kita perlu menanyakan sales_idkolom.

Di bawah ini adalah sintaksis untuk 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

Di sini kita akan membagi data menjadi beberapa file di atas partisi.

masukkan deskripsi gambar di sini

Karena kami telah menentukan 3bucket, masing-masing dibagi menjadi 3 file untuk masing-masing product_id. Ini digunakan secara internal modulo operatoruntuk menentukan di mana masing sales_id- masing ember harus disimpan. Misalnya, untuk product_id='P1', sales_id=1akan disimpan dalam file 000001_0 (yaitu, 1% 3 = 1), sales_id=2akan disimpan dalam file 000002_0 (yaitu, 2% 3 = 2), sales_id=3akan disimpan dalam file 000000_0 (yaitu, 3% 3 = 0) dll.

Sarath Avanavu
sumber
Untuk kolom berkerumun numerik, apakah selalu mengambil mod dengan jumlah ember? Untuk kolom cluster yang bernilai string, apakah ia menggunakan Java hashCode()dari string sebagai fungsi hash? Bisakah programmer memilih fungsi hash?
Don Smith
Rupanya (dan per eksperimen saya) sarang menggunakan variasi pada metode hashCode () Java : github.com/apache/hive/blob/release-1.1.0/serde/src/java/org/… . Ini disebutkan di sini: stackoverflow.com/questions/30594038/… .
Don Smith
3

Perbedaannya adalah membagi ember file dengan Nama Kolom, dan partisi membagi file di bawah Dengan nilai tertentu di dalam tabel

Semoga saya mendefinisikannya dengan benar

uriya harel
sumber
0

Ada banyak tanggapan di sini. Saya ingin membuatnya singkat untuk menghafal perbedaan antara partisi & bucket.

Anda biasanya mempartisi pada kolom yang kurang unik. Dan ember pada kolom paling unik.

Contoh jika Anda menganggap populasi Dunia dengan negara, nama orang, dan id bio-metrik mereka sebagai contoh. Seperti yang bisa Anda tebak, bidang negara akan menjadi kolom yang kurang unik dan bio-metrik id akan menjadi kolom yang paling unik. Jadi idealnya Anda perlu mempartisi tabel berdasarkan negara dan mengisinya dengan bio-metric id.

SVK
sumber
-1

Menggunakan Partisi dalam tabel Hive sangat disarankan karena alasan di bawah ini -

  • Masukkan ke dalam tabel Hive harus lebih cepat (karena menggunakan banyak utas untuk menulis data ke partisi)
  • Permintaan dari tabel Hive harus efisien dengan latensi rendah.

Contoh: -

Asumsikan bahwa File Input (100 GB) dimuat ke dalam tabel temp-hive dan berisi data bank dari berbagai wilayah.

Sarang meja tanpa Partisi

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

Masalah dengan pendekatan ini adalah - Ini akan memindai seluruh data untuk setiap kueri yang Anda jalankan di tabel ini. Waktu respons akan tinggi dibandingkan dengan pendekatan lain di mana partisi dan Bucketing digunakan.

Sarang meja dengan Partisi

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)

Kelebihan - Di sini orang dapat mengakses data lebih cepat ketika datang ke permintaan data untuk transaksi geografi tertentu. Kontra - Memasukkan / meminta data lebih lanjut dapat ditingkatkan dengan memisahkan data di dalam setiap partisi. Lihat opsi Bucketing di bawah ini.

Sarang meja dengan Partisi dan Bucketing

Catatan: Buat tabel sarang ..... dengan "CLUSTERED BY (Partiton_Column) menjadi 5 ember

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)

Pro - Sisipan Lebih Cepat. Permintaan Lebih Cepat.

Kontra - Bucketing akan membuat lebih banyak file. Mungkin ada masalah dengan banyak file kecil dalam beberapa kasus tertentu

Semoga ini bisa membantu !!

Ajay Ahuja
sumber