View a markdown version of this page

Memangkas partisi dinamis - AWS Panduan Preskriptif

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Memangkas partisi dinamis

Spark3.0 dan yang lebih baru termasuk Pemangkasan Partisi Dinamis (DPP). Pemangkasan partisi dinamis adalah teknik pengoptimalan Spark yang mencegah pemindaian partisi yang tidak perlu saat membaca data. Berikut ini adalah beberapa hal penting yang perlu diketahui tentang DPP:

  • Ini memeriksa nilai partisi yang diminta dalam filter kueri dan predikat dan menentukan partisi mana yang diperlukan untuk memenuhi kueri. Setiap partisi yang dianggap tidak perlu dipangkas secara otomatis dan transparan.

  • DPP mengurangi waktu pemrosesan dan pemanfaatan sumber daya dengan melewatkan partisi yang tidak berisi data yang berlaku. Ini membantu Spark untuk fokus hanya pada partisi yang relevan.

  • Ia bekerja dengan partisi statis dan partisi yang dihasilkan secara dinamis yang ditambahkan melalui penyisipan atau beban tambahan. Sparkmengenali partisi baru dan dapat terus menerapkan pemangkasan dinamis.

  • DPP benar-benar transparan atau tidak terlihat oleh pengembang. Tidak diperlukan pengkodean khusus untuk mengaktifkan DPP. Ini terjadi secara otomatis di belakang layar sebagai pengoptimalan selama pembuatan rencana kueri.

Berikut ini adalah beberapa praktik terbaik untuk memastikan DPP bekerja secara efisien:

  • Gunakan pushdown predikat dengan menerapkan filter di awal operasi bingkai Spark data Anda. Ini membantu Spark menghilangkan partisi lebih awal dengan menggunakan metadata partisi.

  • Kumpulkan statistik pada data Anda dengan ANALYZE TABLE sering menjalankannya. Ini mengurangi statistik tingkat kolom yang membantu Spark menentukan partisi mana yang dapat diabaikan secara lebih akurat.

  • Hindari mempartisi data Anda secara berlebihan. Terlalu banyak partisi dapat membebani node driver saat mengumpulkan statistik. Bertujuan untuk 10—100 partisi untuk setiap meja besar.

  • Partisi ulang frame data sebelum bergabung. Hal ini mencegah shuffle join yang memerlukan pemindahan semua data dan selanjutnya mengoptimalkan jumlah data yang dibaca.

  • Gunakan jenis kolom partisi yang konsisten dan penamaan di berbagai tabel yang digabungkan. Ini membantu mencocokkan partisi yang Spark lebih baik untuk pengoptimalan gabungan.

  • Uji kueri dengan EXPLAIN untuk memastikan DPP diterapkan, dan verifikasi apakah penyetelan penambahan diperlukan.

Dalam skema bintang, tabel dibagi menjadi dua jenis utama: tabel fakta dan tabel dimensi. Tabel dimensi cenderung jauh lebih kecil daripada tabel fakta. Saat menggabungkan tabel fakta ke tabel dimensi, DPP mengoptimalkan rencana kueri. Ini menciptakan subquery dari filter apa pun yang diterapkan ke tabel dimensi. Ini menyiarkan subquery ini dan membangun tabel hash darinya. Kemudian menerapkan tabel hash ke fase pemindaian tabel fakta, sebelum membaca data tabel fakta. Ini membantu DPP untuk mengurangi jumlah data yang harus dibaca dari tabel fakta yang lebih besar.

Contoh query berikut menunjukkan DPP dalam tindakan. Kueri mengambil jumlah pesanan dari negara (India) dan menyertakan gabungan batin antara tabel fakta (fact_orders) dan tabel dimensi (nation). fact_ordersTabel dipartisi oleh kolom. o_nationkey

- "select n.n_name as country, count(1) as no_of_orders from fact_orders o join nation n on o.o_nationkey = n.n_nationkey where n.n_name = 'INDIA' group by n.n_name"

Berikut ini adalah langkah-langkah yang digunakan dalam EXPLAIN rencana:

  1. Pindai tabel dimensi yang lebih kecil (nation) dan filter menurut kolomn_name = 'INDIA'.

  2. Siarkan hasil dari langkah sebelumnya.

  3. Buat subquery yang memfilter hasil dari langkah pertama.

  4. Dorong ke bawah sebagai PartitionFilter sehingga hanya memindai partisi tabel fakta yang diperlukan, bukan pemindaian tabel penuh.

Berikut ini adalah EXPLAIN rencana untuk DPP-optimized kueri ini.

== Physical Plan == AdaptiveSparkPlan isFinalPlan=true +- == Final Plan == *(4) HashAggregate(keys=[], functions=[count(1)], output=[count#208L]) +- ShuffleQueryStage 3 +- Exchange SinglePartition, ENSURE_REQUIREMENTS, [id=#353] +- *(3) HashAggregate(keys=[], functions=[partial_count(1)], output=[count#212L]) +- *(3) HashAggregate(keys=[n_name#31], functions=[], output=[]) +- ShuffleQueryStage 1 +- Exchange hashpartitioning(n_name#31, 36), ENSURE_REQUIREMENTS, [id=#315] +- *(2) HashAggregate(keys=[n_name#31], functions=[], output=[n_name#31]) +- *(2) Project [n_name#31] +- *(2) BroadcastHashJoin [cast(o_nationkey#145 as bigint)], [n_nationkey#32L], Inner, BuildRight, false :- *(2) ColumnarToRow : +- FileScan parquet [o_nationkey#145] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[s3://aws-spark-tuning/fact_orders], PartitionFilters: [isnotnull(o_nationkey#145), dynamicpruningexpression(cast(o_nationkey#145 as bigint) IN dynamicp..., PushedFilters: [], ReadSchema: struct<> : +- SubqueryBroadcast dynamicpruning#210, 0, [n_nationkey#32L], [id=#200] : +- OutputAdapter [n_name#31, n_nationkey#32L] : +- AdaptiveSparkPlan isFinalPlan=true : +- BroadcastQueryStage 2 : +- ReusedExchange [n_name#31, n_nationkey#32L], BroadcastExchange HashedRelationBroadcastMode(List(input[1, bigint, false]),false), [id=#233] +- BroadcastQueryStage 0 +- BroadcastExchange HashedRelationBroadcastMode(List(input[1, bigint, false]),false), [id=#233] +- *(1) Filter ((isnotnull(n_name#31) AND (n_name#31 = INDIA)) AND isnotnull(n_nationkey#32L)) +- FileScan json [n_name#31,n_nationkey#32L] Batched: false, DataFilters: [isnotnull(n_name#31), (n_name#31 = INDIA), isnotnull(n_nationkey#32L)], Format: JSON, Location: InMemoryFileIndex[s3://aws-spark-tuning/input/demo/json/nation], PartitionFilters: [], PushedFilters: [IsNotNull(n_name), EqualTo(n_name,INDIA), IsNotNull(n_nationkey)], ReadSchema: struct<n_name:string,n_nationkey:bigint>

Meskipun tidak ada filter langsung yang ditambahkan pada o_nationkey kolom, karena fitur DPP, Spark secara otomatis memindai hanya partisi yang diperlukan, bukan seluruh tabel.