ডেটাফ্রেমের বিভাজনকে কীভাবে সংজ্ঞায়িত করবেন?


128

আমি স্পার্ক 1.4.0 এ স্পার্ক এসকিউএল এবং ডেটাফ্রেম ব্যবহার শুরু করেছি। আমি স্কালায় ডেটাফ্রেমে একটি কাস্টম পার্টিশনারের সংজ্ঞা দিতে চাই, কিন্তু এটি কীভাবে করবেন তা দেখছি না।

আমি যে ডেটা টেবিলের সাথে কাজ করছি তার একটিতে নিম্নলিখিত উদাহরণে সিলিমার অ্যাকাউন্টের মাধ্যমে লেনদেনের একটি তালিকা রয়েছে।

Account   Date       Type       Amount
1001    2014-04-01  Purchase    100.00
1001    2014-04-01  Purchase     50.00
1001    2014-04-05  Purchase     70.00
1001    2014-04-01  Payment    -150.00
1002    2014-04-01  Purchase     80.00
1002    2014-04-02  Purchase     22.00
1002    2014-04-04  Payment    -120.00
1002    2014-04-04  Purchase     60.00
1003    2014-04-02  Purchase    210.00
1003    2014-04-03  Purchase     15.00

অন্তত প্রাথমিকভাবে, বেশিরভাগ গণনা একটি অ্যাকাউন্টের মধ্যে লেনদেনের মধ্যে ঘটে। সুতরাং আমি ডেটা বিভাজনিত করতে চাই যাতে অ্যাকাউন্টের জন্য সমস্ত লেনদেন একই স্পার্ক পার্টিশনে থাকে।

তবে আমি এটি সংজ্ঞায়নের কোনও উপায় দেখছি না। ডেটাফ্রেম শ্রেণিতে একটি পদ্ধতি রয়েছে যার নাম 'পুনরায় বিভাজন (ইন্ট)' রয়েছে, যেখানে আপনি তৈরি করতে পার্টিশনের সংখ্যা নির্দিষ্ট করতে পারেন। তবে আমি কোনও ডেটা ফ্রেমের জন্য কাস্টম পার্টিশনারের সংজ্ঞা দিতে উপলভ্য কোনও পদ্ধতি দেখছি না, যেমন কোনও আরডিডি-র জন্য নির্দিষ্ট করা যেতে পারে।

উত্স ডেটা পারকুইটে সংরক্ষণ করা হয়। আমি দেখেছি যে পরকুইটে ডেটাফ্রেম লেখার সময় আপনি কলামটি পার্টিশনে ভাগ করতে পারেন, সম্ভবত আমি পারকিকেটকে এটি 'অ্যাকাউন্ট' কলামের দ্বারা ডেটা বিভাজন করতে বলতে পারি। তবে লক্ষ লক্ষ অ্যাকাউন্ট থাকতে পারে এবং যদি আমি পারকুইটকে সঠিকভাবে বুঝতে পারি তবে এটি প্রতিটি অ্যাকাউন্টের জন্য একটি স্বতন্ত্র ডিরেক্টরি তৈরি করবে, যাতে এটি যুক্তিসঙ্গত সমাধানের মতো শোনা যায় না।

এই ডেটাফ্রেমকে পার্টিশন করার জন্য স্পার্ক পাওয়ার কোনও উপায় আছে যাতে কোনও অ্যাকাউন্টের সমস্ত ডেটা একই পার্টিশনে থাকে?



আপনি যদি পারকিটকে অ্যাকাউন্ট দ্বারা বিভাজন করতে বলতে পারেন তবে আপনি সম্ভবত ডিরেক্টরি দ্বারা বিভাজন করতে পারেন int(account/someInteger)এবং এর মাধ্যমে ডিরেক্টরি অনুসারে যুক্তিসঙ্গত সংখ্যক অ্যাকাউন্ট পেতে পারেন ।
পল

1
@ এ বি সি: আমি সেই লিঙ্কটি দেখেছি। এই partitionBy(Partitioner)পদ্ধতির সমতুল্য খুঁজছিল, তবে আরডিডিগুলির পরিবর্তে ডেটাফ্রেমগুলির জন্য। আমি এখন দেখতে পাচ্ছি যে partitionByএটি কেবল পেয়ার আরডিডি-র জন্য উপলব্ধ , কেন তা নিশ্চিত তা নয়।
রাক

@ পল: আপনি যা বর্ণনা করেছেন তা করার বিষয়ে আমি বিবেচনা করেছি। কয়েকটি জিনিস আমাকে আটকে
রেখেছে

অব্যাহত .... (1) এটি "ছদ্মবেশ-বিভাজন" এর জন্য। স্পার্ক-পার্টিশনগুলি প্রকৃতপক্ষে পার্কয়েট-পার্টিশন ব্যবহার করবে এমন কোনও দস্তাবেজ আমি খুঁজে পেলাম না। (২) যদি আমি পার্কিট ডকগুলি বুঝতে পারি তবে আমার একটি নতুন ক্ষেত্র "foo" সংজ্ঞায়িত করা দরকার, তবে প্রতিটি পারকুইট ডিরেক্টরিতে "foo = 123" এর মতো নাম থাকবে। তবে যদি আমি অ্যাকাউন্টআইডি জড়িত একটি কোয়েরি তৈরি করি , তবে স্পার্ক / মধুচক্র / শৃঙ্খলা কীভাবে জানতে পারে যে foo এবং অ্যাকাউন্টআইডিআইএর মধ্যে কোনও যোগসূত্র রয়েছে ?
রাক

উত্তর:


177

স্পার্ক> = 2.3.0

স্পার্ক -22614 পরিসীমা বিভাজন প্রকাশ করে।

val partitionedByRange = df.repartitionByRange(42, $"k")

partitionedByRange.explain
// == Parsed Logical Plan ==
// 'RepartitionByExpression ['k ASC NULLS FIRST], 42
// +- AnalysisBarrier Project [_1#2 AS k#5, _2#3 AS v#6]
// 
// == Analyzed Logical Plan ==
// k: string, v: int
// RepartitionByExpression [k#5 ASC NULLS FIRST], 42
// +- Project [_1#2 AS k#5, _2#3 AS v#6]
//    +- LocalRelation [_1#2, _2#3]
// 
// == Optimized Logical Plan ==
// RepartitionByExpression [k#5 ASC NULLS FIRST], 42
// +- LocalRelation [k#5, v#6]
// 
// == Physical Plan ==
// Exchange rangepartitioning(k#5 ASC NULLS FIRST, 42)
// +- LocalTableScan [k#5, v#6]

স্পার্ক -22389 ডেটা সোর্স এপিআই ভি 2 -তে বাহ্যিক ফর্ম্যাট পার্টিশনটি প্রকাশ করে ।

স্পার্ক> = 1.6.0

স্পার্ক> = 1.6 এ কোয়েরি এবং ক্যাশিংয়ের জন্য কলাম দ্বারা বিভাজন ব্যবহার করা সম্ভব। দেখুন: পদ্ধতিটি ব্যবহার করে স্পার্ক -11410 এবং স্পার্ক -4849repartition :

val df = Seq(
  ("A", 1), ("B", 2), ("A", 3), ("C", 1)
).toDF("k", "v")

val partitioned = df.repartition($"k")
partitioned.explain

// scala> df.repartition($"k").explain(true)
// == Parsed Logical Plan ==
// 'RepartitionByExpression ['k], None
// +- Project [_1#5 AS k#7,_2#6 AS v#8]
//    +- LogicalRDD [_1#5,_2#6], MapPartitionsRDD[3] at rddToDataFrameHolder at <console>:27
// 
// == Analyzed Logical Plan ==
// k: string, v: int
// RepartitionByExpression [k#7], None
// +- Project [_1#5 AS k#7,_2#6 AS v#8]
//    +- LogicalRDD [_1#5,_2#6], MapPartitionsRDD[3] at rddToDataFrameHolder at <console>:27
// 
// == Optimized Logical Plan ==
// RepartitionByExpression [k#7], None
// +- Project [_1#5 AS k#7,_2#6 AS v#8]
//    +- LogicalRDD [_1#5,_2#6], MapPartitionsRDD[3] at rddToDataFrameHolder at <console>:27
// 
// == Physical Plan ==
// TungstenExchange hashpartitioning(k#7,200), None
// +- Project [_1#5 AS k#7,_2#6 AS v#8]
//    +- Scan PhysicalRDD[_1#5,_2#6]

RDDsস্পার্কের বিপরীতে Dataset( Dataset[Row]ওরফে সহ DataFrame) এখন পর্যন্ত কাস্টম বিভাজনকারী ব্যবহার করতে পারবেন না। আপনি কৃত্রিম বিভাজন কলাম তৈরি করে সাধারণত এটি সম্বোধন করতে পারেন তবে এটি আপনাকে একই নমনীয়তা দেয় না।

স্পার্ক <1.6.0:

একটি জিনিস আপনি যা করতে পারেন তা হ'ল প্রাক-পার্টিশন ইনপুট ডেটা তৈরির আগে DataFrame

import org.apache.spark.sql.types._
import org.apache.spark.sql.Row
import org.apache.spark.HashPartitioner

val schema = StructType(Seq(
  StructField("x", StringType, false),
  StructField("y", LongType, false),
  StructField("z", DoubleType, false)
))

val rdd = sc.parallelize(Seq(
  Row("foo", 1L, 0.5), Row("bar", 0L, 0.0), Row("??", -1L, 2.0),
  Row("foo", -1L, 0.0), Row("??", 3L, 0.6), Row("bar", -3L, 0.99)
))

val partitioner = new HashPartitioner(5) 

val partitioned = rdd.map(r => (r.getString(0), r))
  .partitionBy(partitioner)
  .values

val df = sqlContext.createDataFrame(partitioned, schema)

যেহেতু DataFrameএকটি থেকে তৈরি করতে RDDকেবলমাত্র একটি সাধারণ মানচিত্রের পর্যায়ে বিদ্যমান পার্টিশন লেআউটটি সংরক্ষণ করা উচিত *:

assert(df.rdd.partitions == partitioned.partitions)

আপনি যেভাবে পুনরায় বিভাজন করতে পারেন একইভাবে DataFrame:

sqlContext.createDataFrame(
  df.rdd.map(r => (r.getInt(1), r)).partitionBy(partitioner).values,
  df.schema
)

সুতরাং দেখে মনে হচ্ছে এটি অসম্ভব নয়। প্রশ্নটি যদি আদৌ বোঝায় তা থেকে যায়। আমি যুক্তি দেব যে বেশিরভাগ সময় এটি হয় না:

  1. পুনঃবিভাজন একটি ব্যয়বহুল প্রক্রিয়া। একটি সাধারণ দৃশ্যে বেশিরভাগ ডেটা সিরিয়ালাইজড, বদলানো এবং ডিসিরিয়ালাইজড করতে হয়। অপরদিকে অপারেশনগুলির সংখ্যা যা পূর্ব-বিভাজিত ডেটা থেকে উপকার পেতে পারে তা তুলনামূলকভাবে কম এবং যদি অভ্যন্তরীণ এপিআই এই সম্পত্তিটি উত্তোলনের জন্য ডিজাইন না করা হয় তবে আরও সীমাবদ্ধ।

    • কিছু পরিস্থিতিতে যোগ দেয়, তবে এটির জন্য অভ্যন্তরীণ সহায়তা প্রয়োজন,
    • উইন্ডো ফাংশন মেলা বিভাজক সঙ্গে কল। উপরের মত একই, একক উইন্ডো সংজ্ঞাতে সীমাবদ্ধ। এটি ইতিমধ্যে অভ্যন্তরীণভাবে বিভক্ত হয়েছে, সুতরাং প্রাক-বিভাজন অপ্রয়োজনীয় হতে পারে,
    • এর সাথে সরল সমষ্টি GROUP BY- অস্থায়ী বাফারগুলির ** মেমরির পদচিহ্ন হ্রাস করা সম্ভব তবে সামগ্রিক ব্যয় অনেক বেশি। কমবেশি groupByKey.mapValues(_.reduce)(বর্তমান আচরণ) বনাম reduceByKey(পূর্ব-পার্টিশন) এর সমান । অনুশীলনে কার্যকর হতে পারে না।
    • সঙ্গে ডেটা সংকোচনের SqlContext.cacheTable। যেহেতু দেখে মনে হচ্ছে এটি রান দৈর্ঘ্যের এনকোডিং ব্যবহার করছে, প্রয়োগ করা OrderedRDDFunctions.repartitionAndSortWithinPartitionsসংক্ষেপণের অনুপাতকে উন্নত করতে পারে।
  2. পারফরম্যান্স কীগুলি বিতরণের উপর অত্যন্ত নির্ভরশীল। যদি এটি স্কিউ করা হয় তবে এর ফলে সাবপটিমাল রিসোর্স ব্যবহার হবে। সবচেয়ে খারাপ পরিস্থিতিতে দৃশ্যে কাজটি শেষ করা মোটেও অসম্ভব।

  3. উচ্চ স্তরের ঘোষণামূলক এপিআই ব্যবহারের সম্পূর্ণ পয়েন্টটি হ'ল নিম্ন স্তরের প্রয়োগের বিশদ থেকে নিজেকে বিচ্ছিন্ন করা। @Dwysakowicz এবং @RomiKuntsman দ্বারা ইতিমধ্যে উল্লিখিত হিসাবে একটি অপ্টিমাইজেশন ক্যাটালিস্ট অপ্টিমাইজারের কাজ । এটি একটি সুন্দর পরিশীলিত জন্তু এবং আমি সত্যিই সন্দেহ করি যে এর অভ্যন্তরের অভ্যন্তরে গভীর গভীরতা না ডেকেই আপনি সহজেই এর উন্নতি করতে পারেন।

সম্পর্কিত ধারণা

জেডিবিসি সূত্রগুলির সাথে বিভাজন :

জেডিবিসি ডেটা সূত্রগুলি predicatesযুক্তি সমর্থন করে । এটি নিম্নলিখিত হিসাবে ব্যবহার করা যেতে পারে:

sqlContext.read.jdbc(url, table, Array("foo = 1", "foo = 3"), props)

এটি পূর্বাভাস অনুযায়ী একক জেডিবিসি পার্টিশন তৈরি করে। মনে রাখবেন যে পৃথক পূর্বাভাসগুলি ব্যবহার করে তৈরি সেটগুলি যদি বিঘ্নিত না হয় তবে আপনি ফলাফল সারণিতে নকল দেখতে পাবেন।

partitionByপদ্ধতিতেDataFrameWriter :

স্পার্ক DataFrameWriterএকটি partitionByপদ্ধতি প্রদান করে যা লেখার ক্ষেত্রে "পার্টিশন" ডেটা ব্যবহার করতে পারে। এটি প্রদত্ত কলামগুলির সেট ব্যবহার করে লেখার ডেটা পৃথক করে

val df = Seq(
  ("foo", 1.0), ("bar", 2.0), ("foo", 1.5), ("bar", 2.6)
).toDF("k", "v")

df.write.partitionBy("k").json("/tmp/foo.json")

এটি কী-এর উপর ভিত্তি করে প্রশ্নের জন্য পঠন-পাঠের প্রস্তাবটিকে সক্ষম করে:

val df1 = sqlContext.read.schema(df.schema).json("/tmp/foo.json")
df1.where($"k" === "bar")

তবে এটি সমান নয় DataFrame.repartition। বিশেষ একত্রিতে যেমন:

val cnts = df1.groupBy($"k").sum()

এখনও প্রয়োজন হবে TungstenExchange:

cnts.explain

// == Physical Plan ==
// TungstenAggregate(key=[k#90], functions=[(sum(v#91),mode=Final,isDistinct=false)], output=[k#90,sum(v)#93])
// +- TungstenExchange hashpartitioning(k#90,200), None
//    +- TungstenAggregate(key=[k#90], functions=[(sum(v#91),mode=Partial,isDistinct=false)], output=[k#90,sum#99])
//       +- Scan JSONRelation[k#90,v#91] InputPaths: file:/tmp/foo.json

bucketBy পদ্ধতিতে DataFrameWriter (স্পার্ক> = ২.০):

bucketByঅনুরূপ অ্যাপ্লিকেশন রয়েছে partitionByতবে এটি কেবল টেবিলগুলির জন্য উপলব্ধ ( saveAsTable)। বুকিংয়ের তথ্যগুলি যোগদানের অনুকূলিত করতে ব্যবহার করতে পারে:

// Temporarily disable broadcast joins
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)

df.write.bucketBy(42, "k").saveAsTable("df1")
val df2 = Seq(("A", -1.0), ("B", 2.0)).toDF("k", "v2")
df2.write.bucketBy(42, "k").saveAsTable("df2")

// == Physical Plan ==
// *Project [k#41, v#42, v2#47]
// +- *SortMergeJoin [k#41], [k#46], Inner
//    :- *Sort [k#41 ASC NULLS FIRST], false, 0
//    :  +- *Project [k#41, v#42]
//    :     +- *Filter isnotnull(k#41)
//    :        +- *FileScan parquet default.df1[k#41,v#42] Batched: true, Format: Parquet, Location: InMemoryFileIndex[file:/spark-warehouse/df1], PartitionFilters: [], PushedFilters: [IsNotNull(k)], ReadSchema: struct<k:string,v:int>
//    +- *Sort [k#46 ASC NULLS FIRST], false, 0
//       +- *Project [k#46, v2#47]
//          +- *Filter isnotnull(k#46)
//             +- *FileScan parquet default.df2[k#46,v2#47] Batched: true, Format: Parquet, Location: InMemoryFileIndex[file:/spark-warehouse/df2], PartitionFilters: [], PushedFilters: [IsNotNull(k)], ReadSchema: struct<k:string,v2:double>

* পার্টিশন লেআউট দ্বারা আমি কেবল একটি ডেটা বন্টন বোঝাতে চাইছি। partitionedআরডিডি-র আর কোনও বিভাজন নেই। ** প্রাথমিক প্রজেকশন ধরে নিচ্ছি না। সমষ্টি যদি কলামগুলির কেবলমাত্র ছোট উপসেটকে কভার করে তবে সম্ভবত কোনও লাভ নেই।


হ্যাঁ এবং না ডেটা বিন্যাস সংরক্ষণ করা হবে তবে এএফআইএকি এটি আপনাকে বিভাজন ছাঁটাইয়ের মতো সুবিধা দেয় না।
শূন্য323

@ শূন্য ৩৩৩ ধন্যবাদ, df.save.writte লেআউটটি সংরক্ষণ করার জন্য parquet ফাইলের পার্টিশন বরাদ্দ চেক করার কোনও উপায় আছে? এবং যদি আমি df.repartition ("A") করি, তবে df.write.repartitionBy ("B") করে ফিজিকাল ফোল্ডার কাঠামো বি দ্বারা বিভাজনিত হবে এবং প্রতিটি বি মান ফোল্ডারের মধ্যে কি এটি এখনও পার্টিশনটি রেখে যাবে? একজন?
বাইচেন

2
@ বাইচেন্স DataFrameWriter.partitionByযৌক্তিকভাবে এর মতো নয় DataFrame.repartition। প্রাক্তন এলোমেলো হয় না, এটি কেবল আউটপুট পৃথক করে। প্রথম প্রশ্ন সম্পর্কিত - পার্টিশন অনুযায়ী ডেটা সংরক্ষণ করা হয় এবং কোনও পরিবর্তন হয় না। আপনি স্বতন্ত্র ফাইলগুলি পড়ে সহজেই এটি পরীক্ষা করতে পারেন। তবে আপনি যদি সত্যিই এটি চান তবে স্পার্কের একারও এটি সম্পর্কে জানার কোনও উপায় নেই।
শূন্য323

11

স্পার্কে <1.6 আপনি যদি একটি তৈরি করেন HiveContextতবে সরল পুরাতন SqlContextআপনি হাইভকিউএল ব্যবহার করতে পারবেন DISTRIBUTE BY colX...(এন এর প্রত্যেকটি হ্রাসকারী এক্স এর নন-ওভারল্যাপিং রেঞ্জগুলি নিশ্চিত করে CLUSTER BY colX...) এবং উদাহরণস্বরূপ (ডিস্ট্রিবিউট বাই অ্যান্ড বাছাইয়ের শর্টকাট);

df.registerTempTable("partitionMe")
hiveCtx.sql("select * from partitionMe DISTRIBUTE BY accountId SORT BY accountId, date")

স্পার্ক ডিএফ এপিআইয়ের সাথে এটি কীভাবে খাপ খায় তা নিশ্চিত নয়। এই কীওয়ার্ডগুলি সাধারণ স্কেলকন্টেক্সটে সমর্থিত নয় (নোট করুন হিভকনেক্সটেক্স ব্যবহার করার জন্য আপনার মাইভ মেটা স্টোর লাগবে না)

সম্পাদনা: স্পার্ক 1.6+ এর এখন নেটিভ ডেটা ফ্রেম এপিআইতে রয়েছে


1
ডেটাফ্রেম সংরক্ষণের সাথে সাথে পার্টিশনগুলি সংরক্ষণ করা আছে?
সিম

এইচআইএল QL উদাহরণে আপনার কতগুলি পার্টিশন থাকতে পারে তা আপনি কীভাবে নিয়ন্ত্রণ করবেন? উদাহরণস্বরূপ, জোড় আরডিডি পদ্ধতির ক্ষেত্রে, আপনি 5 টি পার্টিশন তৈরি করতে এটি করতে পারেন: ভাল পার্টিশনার = নতুন হ্যাশ পার্টিশনার (5)
মেনি

ঠিক আছে, উত্তরটি খুঁজে পেয়েছি, এটি এটির মতো করা যেতে পারে: sqlContext.setConf ("spark.sql.shuffle.partitions", "5") আমি 5 মিনিটের সীমা মিস করায় পূর্ববর্তী মন্তব্য সম্পাদনা করতে পারিনি
Minnie

7

তাই একরকম উত্তর দিয়ে শুরু করতে:) - আপনি পারবেন না

আমি কোনও বিশেষজ্ঞ নই, তবে যতদূর আমি ডেটাফ্রেমগুলি বুঝতে পারি, সেগুলি আরডিডি-র সমান নয় এবং ডেটাফ্রেমে পার্টিশনারের মতো কোনও জিনিস নেই।

সাধারণত ডেটাফ্রেমের ধারণা হ'ল বিমূর্তির আরেকটি স্তর সরবরাহ করা যা এ জাতীয় সমস্যা নিজেই পরিচালনা করে। ডেটাফ্রেমের প্রশ্নগুলি লজিক্যাল পরিকল্পনায় অনুবাদ করা হয় যা আরডিডি-র ক্রিয়াকলাপে আরও অনুবাদ করা হয়। আপনার প্রস্তাবিত পার্টিশনটি সম্ভবত স্বয়ংক্রিয়ভাবে প্রয়োগ করা হবে বা কমপক্ষে হওয়া উচিত।

আপনি যদি স্পার্কএসকিউএল-তে বিশ্বাস না করেন যে এটি একরকম অনুকূল কাজ প্রদান করবে, তবে আপনি মন্তব্যগুলির পরামর্শ অনুসারে ডেটাফ্রেমকে আরডিডি [সারি] তে সর্বদা রূপান্তর করতে পারেন।


7

এর দ্বারা ফিরিয়ে নেওয়া ডেটাফ্রেম ব্যবহার করুন:

yourDF.orderBy(account)

ব্যবহারের কোনও সুস্পষ্ট উপায় নেই partitionByকেবলমাত্র পেয়ারআরডিডি তে কোনও ডেটা ফ্রেমে , তবে আপনি যখন কোনও ডেটা ফ্রেম বাছাই করবেন তখন এটি লজিক্যালপ্ল্যানে এটি ব্যবহার করবে এবং যখন আপনাকে প্রতিটি অ্যাকাউন্টে গণনা করা দরকার তখন এটি সাহায্য করবে।

আমি ঠিক একই সমস্যাটি নিয়ে হোঁচট খেয়েছি, এমন একটি ডেটা ফ্রেম যা আমি অ্যাকাউন্টে বিভাজন করতে চাই। আমি ধরে নিয়েছি যে আপনি যখন "ডেটা বিভক্ত করতে চান যাতে কোনও অ্যাকাউন্টের জন্য সমস্ত লেনদেন একই স্পার্ক পার্টিশনে থাকে", আপনি এটি স্কেল এবং পারফরম্যান্সের জন্য চান তবে আপনার কোড এটির উপর নির্ভর করে না (যেমন ব্যবহার করার মতো) mapPartitions()ইত্যাদি), তাই না?


3
আপনার মানচিত্রের বিভাগগুলি ব্যবহার করার কারণে যদি আপনার কোডটি এর উপর নির্ভর করে তবে কী হবে?
নাইটওয়াল্ফ

2
আপনি ডেটাফ্রেমকে একটি আরডিডিতে রূপান্তর করতে পারেন এবং তারপরে এটি পার্টিশন করতে পারেন (উদাহরণস্বরূপ aggregatByKey () ব্যবহার করে এবং একটি কাস্টম পার্টিশনার পাস করুন)
রোমি কুনটসম্যান

5

আমি আরডিডি ব্যবহার করে এটি করতে সক্ষম হয়েছি। তবে এটি আপনার পক্ষে গ্রহণযোগ্য সমাধান কিনা তা আমি জানি না। একবার আপনার আরডিডি হিসাবে ডিএফ পাওয়া গেলে আপনি আবেদন করতে পারবেনrepartitionAndSortWithinPartitions তথ্যের কাস্টম পুনঃবিভাজন সম্পাদনের জন্য করতে পারেন।

আমি ব্যবহৃত একটি নমুনা এখানে:

class DatePartitioner(partitions: Int) extends Partitioner {

  override def getPartition(key: Any): Int = {
    val start_time: Long = key.asInstanceOf[Long]
    Objects.hash(Array(start_time)) % partitions
  }

  override def numPartitions: Int = partitions
}

myRDD
  .repartitionAndSortWithinPartitions(new DatePartitioner(24))
  .map { v => v._2 }
  .toDF()
  .write.mode(SaveMode.Overwrite)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.