This is an automated email from the ASF dual-hosted git repository.

zhouyuan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gluten.git


The following commit(s) were added to refs/heads/main by this push:
     new 7374ac276e [VL] Support parquet.enable.page.index write option (#12760)
7374ac276e is described below

commit 7374ac276e990dd73ef3e440057247917538a1ef
Author: EJ Song <[email protected]>
AuthorDate: Tue Aug 18 05:53:12 2026 -0700

    [VL] Support parquet.enable.page.index write option (#12760)
    
    Add a parquet.enable.page.index write option that maps to the Velox
    ParquetWriterOptions::enableWritePageIndex field 
(facebookincubator/velox#18325):
---
 .../velox/VeloxParquetWriterInjects.scala          |  1 +
 .../sql/execution/VeloxParquetWriteSuite.scala     | 51 ++++++++++++++++++++++
 cpp/core/config/GlutenConfig.h                     |  2 +
 cpp/velox/utils/VeloxWriterUtils.cc                |  8 ++++
 docs/velox-parquet-write-configuration.md          |  2 +-
 .../org/apache/gluten/config/GlutenConfig.scala    |  1 +
 6 files changed, 64 insertions(+), 1 deletion(-)

diff --git 
a/backends-velox/src/main/scala/org/apache/spark/sql/execution/datasources/velox/VeloxParquetWriterInjects.scala
 
b/backends-velox/src/main/scala/org/apache/spark/sql/execution/datasources/velox/VeloxParquetWriterInjects.scala
index 1244aab279..45f9b0b747 100644
--- 
a/backends-velox/src/main/scala/org/apache/spark/sql/execution/datasources/velox/VeloxParquetWriterInjects.scala
+++ 
b/backends-velox/src/main/scala/org/apache/spark/sql/execution/datasources/velox/VeloxParquetWriterInjects.scala
@@ -55,6 +55,7 @@ class VeloxParquetWriterInjects extends 
VeloxFormatWriterInjects {
       GlutenConfig.PARQUET_ZSTD_COMPRESSION_LEVEL,
       GlutenConfig.PARQUET_DATAPAGE_SIZE,
       GlutenConfig.PARQUET_ENABLE_DICTIONARY,
+      GlutenConfig.PARQUET_ENABLE_PAGE_INDEX,
       GlutenConfig.PARQUET_WRITER_VERSION
     ).foreach(key => options.get(key).foreach(sparkOptions.put(key, _)))
     sparkOptions.asJava
diff --git 
a/backends-velox/src/test/scala/org/apache/spark/sql/execution/VeloxParquetWriteSuite.scala
 
b/backends-velox/src/test/scala/org/apache/spark/sql/execution/VeloxParquetWriteSuite.scala
index fcd5d45e6c..9a6d423ed2 100644
--- 
a/backends-velox/src/test/scala/org/apache/spark/sql/execution/VeloxParquetWriteSuite.scala
+++ 
b/backends-velox/src/test/scala/org/apache/spark/sql/execution/VeloxParquetWriteSuite.scala
@@ -306,6 +306,57 @@ class VeloxParquetWriteSuite extends 
VeloxWholeStageTransformerSuite with WriteU
         checkAnswer(parquetDf, spark.range(100).toDF("id"))
     }
   }
+
+  test("test write parquet with page index enabled/disabled/default") {
+    Seq(Some(true), Some(false), None).foreach {
+      enablePageIndex =>
+        withTempPath {
+          f =>
+            val writer = spark
+              .range(0, 100000, 1, 1)
+              .selectExpr("id", "cast(id % 100 as int) as v")
+              .write
+              .format("parquet")
+              .option(GlutenConfig.PARQUET_DATAPAGE_SIZE, (4 * 1024).toString)
+            enablePageIndex.foreach(
+              v => writer.option(GlutenConfig.PARQUET_ENABLE_PAGE_INDEX, 
v.toString))
+            writer.save(f.getCanonicalPath)
+
+            val expectPageIndex = enablePageIndex.getOrElse(true)
+            val parquetFiles = f.list((_, name) => name.contains("parquet"))
+            assert(parquetFiles.nonEmpty)
+            val indexRefs = parquetFiles.flatMap {
+              file =>
+                val path = new Path(f.getCanonicalPath, file)
+                val in = HadoopInputFile.fromPath(path, 
spark.sessionState.newHadoopConf())
+                Utils.tryWithResource(ParquetFileReader.open(in)) {
+                  reader =>
+                    reader.getFooter.getBlocks.asScala.flatMap {
+                      block =>
+                        block.getColumns.asScala.map {
+                          col =>
+                            (
+                              col.getColumnIndexReference != null,
+                              col.getOffsetIndexReference != null)
+                        }
+                    }
+                }
+            }
+            val hasColumnIndex = indexRefs.exists(_._1)
+            val hasOffsetIndex = indexRefs.exists(_._2)
+            assert(
+              hasColumnIndex == expectPageIndex,
+              s"expected column index present=$expectPageIndex but found 
$hasColumnIndex")
+            assert(
+              hasOffsetIndex == expectPageIndex,
+              s"expected offset index present=$expectPageIndex but found 
$hasOffsetIndex")
+
+            checkAnswer(
+              spark.read.parquet(f.getCanonicalPath),
+              spark.range(0, 100000, 1, 1).selectExpr("id", "cast(id % 100 as 
int) as v"))
+        }
+    }
+  }
 }
 
 class VeloxParquetWriteHadoopConfSuite extends VeloxWholeStageTransformerSuite 
with WriteUtils {
diff --git a/cpp/core/config/GlutenConfig.h b/cpp/core/config/GlutenConfig.h
index 9c55628991..dae818c57c 100644
--- a/cpp/core/config/GlutenConfig.h
+++ b/cpp/core/config/GlutenConfig.h
@@ -70,6 +70,8 @@ const std::string kParquetDataPageSize = "parquet.page.size";
 
 const std::string kParquetEnableDictionary = "parquet.enable.dictionary";
 
+const std::string kParquetEnablePageIndex = "parquet.enable.page.index";
+
 const std::string kParquetWriterVersion = "parquet.writer.version";
 
 const std::string kParquetCompressionCodec = 
"spark.sql.parquet.compression.codec";
diff --git a/cpp/velox/utils/VeloxWriterUtils.cc 
b/cpp/velox/utils/VeloxWriterUtils.cc
index 52551787c2..68987edd99 100644
--- a/cpp/velox/utils/VeloxWriterUtils.cc
+++ b/cpp/velox/utils/VeloxWriterUtils.cc
@@ -129,6 +129,14 @@ 
std::shared_ptr<facebook::velox::dwio::common::WriterOptions> makeParquetWriteOp
       parquetOptions->enableDictionary = false;
     }
   }
+  // Write the Parquet page index (column index + offset index) by default to 
match
+  // Spark/parquet-mr (SPARK-26345); Velox's writer leaves it opt-in. Disable 
with
+  // parquet.enable.page.index=false.
+  bool enableWritePageIndex = true;
+  if (auto it = sparkConfs.find(kParquetEnablePageIndex); it != 
sparkConfs.end()) {
+    enableWritePageIndex = boost::iequals(it->second, "true");
+  }
+  parquetOptions->enableWritePageIndex = enableWritePageIndex;
   writeOption->formatSpecificOptions = std::move(parquetOptions);
   return writeOption;
 }
diff --git a/docs/velox-parquet-write-configuration.md 
b/docs/velox-parquet-write-configuration.md
index 69a5d21c19..a408df8c6b 100644
--- a/docs/velox-parquet-write-configuration.md
+++ b/docs/velox-parquet-write-configuration.md
@@ -54,7 +54,7 @@ df.write.option("parquet.block.rows").save()
        </tr>
        <tr>
                <td><code>page_index</code></td>
-               <td></td><td></td><td>false</td><td></td>
+               
<td></td><td></td><td>true</td><td>parquet.enable.page.index</td>
        </tr>
        <tr>
                <td><code>decimal_as_integer</code></td>
diff --git 
a/gluten-substrait/src/main/scala/org/apache/gluten/config/GlutenConfig.scala 
b/gluten-substrait/src/main/scala/org/apache/gluten/config/GlutenConfig.scala
index 3bb5b0958f..4971d89dd0 100644
--- 
a/gluten-substrait/src/main/scala/org/apache/gluten/config/GlutenConfig.scala
+++ 
b/gluten-substrait/src/main/scala/org/apache/gluten/config/GlutenConfig.scala
@@ -416,6 +416,7 @@ object GlutenConfig extends ConfigRegistry {
   val PARQUET_ZSTD_COMPRESSION_LEVEL: String = 
"parquet.compression.codec.zstd.level"
   val PARQUET_DATAPAGE_SIZE: String = "parquet.page.size"
   val PARQUET_ENABLE_DICTIONARY: String = "parquet.enable.dictionary"
+  val PARQUET_ENABLE_PAGE_INDEX: String = "parquet.enable.page.index"
   val PARQUET_WRITER_VERSION: String = "parquet.writer.version"
   // Hadoop config
   val HADOOP_PREFIX = "spark.hadoop."


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to