shangxinli commented on code in PR #18990:
URL: https://github.com/apache/hudi/pull/18990#discussion_r4425871145


##########
hudi-client/hudi-spark-client/src/main/scala/org/apache/hudi/HoodieDatasetBulkInsertHelper.scala:
##########
@@ -146,6 +188,84 @@ object HoodieDatasetBulkInsertHelper
     partitioner.repartitionRecords(updatedDF, targetParallelism)
   }
 
+  /**
+   * Builds the record-key / partition-path projection columns for the non 
auto-keygen path,
+   * dispatching to a fast-path tier when the keygen is amenable to a pure 
Catalyst projection.
+   *
+   * Tier 1: NonpartitionedKeyGenerator with a single record-key field.
+   * Tier 2: SimpleKeyGenerator with a single record-key + single 
partition-path field, when the
+   *         partition formatter flags are reproducible as Catalyst 
expressions. Currently:
+   *         default flags, or hive-style partitioning. URL-encoded and 
slash-separated date
+   *         partitioning fall through to Tier 3 -- the URL escape table 
doesn't have an efficient
+   *         pure-Catalyst equivalent, and slash-separated dates were added in 
1.2.0 and exercise
+   *         a separate formatter branch we'd rather not encode twice.
+   * Tier 3: Anonymous UDF that calls into the supplied 
[[BuiltinKeyGenerator]].
+   */
+  private def buildKeygenColumns(df: DataFrame,
+                                 keyGeneratorClassName: String,
+                                 typedProps: TypedProperties,
+                                 keyGenerator: BuiltinKeyGenerator): 
(org.apache.spark.sql.Column, org.apache.spark.sql.Column) = {
+    val recordKeyFields = keyGenerator.getRecordKeyFieldNames
+    val partitionPathFields = keyGenerator.getPartitionPathFields
+
+    val hiveStyle = 
typedProps.getBoolean(KeyGeneratorOptions.HIVE_STYLE_PARTITIONING_ENABLE.key,
+      
KeyGeneratorOptions.HIVE_STYLE_PARTITIONING_ENABLE.defaultValue.toBoolean)
+    val urlEncode = 
typedProps.getBoolean(KeyGeneratorOptions.URL_ENCODE_PARTITIONING.key,
+      KeyGeneratorOptions.URL_ENCODE_PARTITIONING.defaultValue.toBoolean)
+    val slashSep = 
typedProps.getBoolean(KeyGeneratorOptions.SLASH_SEPARATED_DATE_PARTITIONING.key,
+      
KeyGeneratorOptions.SLASH_SEPARATED_DATE_PARTITIONING.defaultValue.toBoolean)
+
+    val tier1 = keyGeneratorClassName == 
classOf[NonpartitionedKeyGenerator].getName &&
+      recordKeyFields.size == 1
+
+    val tier2 = keyGeneratorClassName == classOf[SimpleKeyGenerator].getName &&
+      recordKeyFields.size == 1 && partitionPathFields.size == 1 &&
+      !urlEncode && !slashSep
+
+    if (tier1) {
+      (functions.col(recordKeyFields.get(0)).cast(StringType),
+        functions.lit("").cast(StringType))
+    } else if (tier2) {
+      val recordKeyCol = functions.col(recordKeyFields.get(0)).cast(StringType)
+      val partitionPathCol = 
buildSimpleKeygenPartitionPathColumn(partitionPathFields.get(0), hiveStyle)
+      (recordKeyCol, partitionPathCol)
+    } else {
+      val recordKeyUdf = functions.udf(
+        new UDF1[Row, String] { override def call(row: Row): String = 
keyGenerator.getRecordKey(row) },

Review Comment:
   The tier 3 fallback calls the single-arg getRecordKey/getPartitionPath(Row) 
overloads, which BuiltinKeyGenerator itself notes as having considerable 
overhead versus the schema-qualified overloads, so these keygens may end up 
slower per record than the old RDD path.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to