This is an automated email from the ASF dual-hosted git repository.
emkornfield pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new e8ab3ae ARROW-13733 [Java]: Allow JDBC adapters to reuse vector
schema roots
e8ab3ae is described below
commit e8ab3ae5ccd1c3979dfe22d8fdf204fcedb8b215
Author: liyafan82 <[email protected]>
AuthorDate: Sun Sep 12 14:23:52 2021 -0700
ARROW-13733 [Java]: Allow JDBC adapters to reuse vector schema roots
According to the current design of the JDBC adapter, it is not possible to
reuse the vector schema roots. That is, a new vector schema root is created and
released for each batch.
This can cause performance problems, because in many scenarios, the client
code only reads data in vector schema root. So the vector schema roots can be
reused in the following cycle: populate data -> client use data -> populate
data -> ...
The current design has another problem. For most times, it has two
alternating vector schema roots in memory, causing a large waste of memory,
especially for large batches.
We solve both problems by providing a flag in the config, which allows the
user to reuse the vector shema roots.
Closes #10983 from liyafan82/fly_0824_jd
Authored-by: liyafan82 <[email protected]>
Signed-off-by: Micah Kornfield <[email protected]>
---
.../arrow/adapter/jdbc/ArrowVectorIterator.java | 50 +++++++++++-----------
.../arrow/adapter/jdbc/JdbcToArrowConfig.java | 18 +++++++-
.../adapter/jdbc/JdbcToArrowConfigBuilder.java | 9 ++++
.../adapter/jdbc/AbstractJdbcToArrowTest.java | 1 +
.../arrow/adapter/jdbc/JdbcToArrowConfigTest.java | 10 +++--
.../arrow/adapter/jdbc/h2/JdbcToArrowTest.java | 27 ++++++++----
.../jdbc/h2/JdbcToArrowVectorIteratorTest.java | 50 +++++++++++++++++++---
7 files changed, 122 insertions(+), 43 deletions(-)
diff --git
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/ArrowVectorIterator.java
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/ArrowVectorIterator.java
index e445056..0e833bc 100644
---
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/ArrowVectorIterator.java
+++
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/ArrowVectorIterator.java
@@ -46,6 +46,7 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
private final JdbcConsumer[] consumers;
final CompositeJdbcConsumer compositeConsumer;
+ // this is used only if resuing vector schema root is enabled.
private VectorSchemaRoot nextBatch;
private final int targetBatchSize;
@@ -73,7 +74,7 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
arrowType, i, isColumnNullable(resultSet, i), null, config);
}
- load(createVectorSchemaRoot());
+ this.nextBatch = config.isReuseVectorSchemaRoot() ?
createVectorSchemaRoot() : null;
}
/**
@@ -83,15 +84,17 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
ResultSet resultSet,
JdbcToArrowConfig config)
throws SQLException {
-
- ArrowVectorIterator iterator = new ArrowVectorIterator(resultSet, config);
+ ArrowVectorIterator iterator = null;
try {
+ iterator = new ArrowVectorIterator(resultSet, config);
iterator.initialize();
- return iterator;
- } catch (Exception e) {
- iterator.close();
+ } catch (Throwable e) {
+ if (iterator != null) {
+ iterator.close();
+ }
throw new RuntimeException("Error occurred while creating iterator.", e);
}
+ return iterator;
}
private void consumeData(VectorSchemaRoot root) {
@@ -111,9 +114,8 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
}
}
-
root.setRowCount(readRowCount);
- } catch (Exception e) {
+ } catch (Throwable e) {
compositeConsumer.close();
throw new RuntimeException("Error occurred while consuming data.", e);
}
@@ -126,7 +128,7 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
if (config.getTargetBatchSize() !=
JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE) {
ValueVectorUtility.preAllocate(root, config.getTargetBatchSize());
}
- } catch (Exception e) {
+ } catch (Throwable e) {
if (root != null) {
root.close();
}
@@ -137,40 +139,38 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
// Loads the next schema root or null if no more rows are available.
private void load(VectorSchemaRoot root) throws SQLException {
-
- for (int i = 1; i <= consumers.length; i++) {
- consumers[i -
1].resetValueVector(root.getVector(rsmd.getColumnLabel(i)));
+ for (int i = 0; i < consumers.length; i++) {
+ consumers[i].resetValueVector(root.getVector(i));
}
consumeData(root);
-
- if (root.getRowCount() == 0) {
- root.close();
- nextBatch = null;
- } else {
- nextBatch = root;
- }
}
@Override
public boolean hasNext() {
- return nextBatch != null;
+ try {
+ return !resultSet.isAfterLast();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
}
/**
- * Gets the next vector. The user is responsible for freeing its resources.
+ * Gets the next vector.
+ * If {@link JdbcToArrowConfig#isReuseVectorSchemaRoot()} is false,
+ * the client is responsible for freeing its resources.
*/
@Override
public VectorSchemaRoot next() {
Preconditions.checkArgument(hasNext());
- VectorSchemaRoot returned = nextBatch;
try {
- load(createVectorSchemaRoot());
+ VectorSchemaRoot ret = config.isReuseVectorSchemaRoot() ? nextBatch :
createVectorSchemaRoot();
+ load(ret);
+ return ret;
} catch (Exception e) {
close();
throw new RuntimeException("Error occurred while getting next schema
root.", e);
}
- return returned;
}
/**
@@ -178,7 +178,7 @@ public class ArrowVectorIterator implements
Iterator<VectorSchemaRoot>, AutoClos
*/
@Override
public void close() {
- if (nextBatch != null) {
+ if (config.isReuseVectorSchemaRoot()) {
nextBatch.close();
}
compositeConsumer.close();
diff --git
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java
index 9a587e7..250b0ed 100644
---
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java
+++
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfig.java
@@ -58,6 +58,7 @@ public final class JdbcToArrowConfig {
private final Calendar calendar;
private final BufferAllocator allocator;
private final boolean includeMetadata;
+ private final boolean reuseVectorSchemaRoot;
private final Map<Integer, JdbcFieldInfo> arraySubTypesByColumnIndex;
private final Map<String, JdbcFieldInfo> arraySubTypesByColumnName;
@@ -87,7 +88,12 @@ public final class JdbcToArrowConfig {
* @param calendar The calendar to use when constructing Timestamp
fields and reading time-based results.
*/
JdbcToArrowConfig(BufferAllocator allocator, Calendar calendar) {
- this(allocator, calendar, false, null, null, DEFAULT_TARGET_BATCH_SIZE,
null);
+ this(allocator, calendar,
+ /* include metadata */ false,
+ /* reuse vector schema root */ false,
+ /* array sub-types by column index */ null,
+ /* array sub-types by column name */ null,
+ DEFAULT_TARGET_BATCH_SIZE, null);
}
/**
@@ -98,6 +104,7 @@ public final class JdbcToArrowConfig {
* @param allocator The memory allocator to construct the Arrow
vectors with.
* @param calendar The calendar to use when constructing Timestamp
fields and reading time-based results.
* @param includeMetadata Whether to include JDBC field metadata in the
Arrow Schema Field metadata.
+ * @param reuseVectorSchemaRoot Whether to reuse the vector schema root for
each data load.
* @param arraySubTypesByColumnIndex The type of the JDBC array at the
column index (1-based).
* @param arraySubTypesByColumnName The type of the JDBC array at the
column name.
* @param jdbcToArrowTypeConverter The function that maps JDBC field type
information to arrow type. If set to null,
@@ -134,6 +141,7 @@ public final class JdbcToArrowConfig {
BufferAllocator allocator,
Calendar calendar,
boolean includeMetadata,
+ boolean reuseVectorSchemaRoot,
Map<Integer, JdbcFieldInfo> arraySubTypesByColumnIndex,
Map<String, JdbcFieldInfo> arraySubTypesByColumnName,
int targetBatchSize,
@@ -142,6 +150,7 @@ public final class JdbcToArrowConfig {
this.allocator = allocator;
this.calendar = calendar;
this.includeMetadata = includeMetadata;
+ this.reuseVectorSchemaRoot = reuseVectorSchemaRoot;
this.arraySubTypesByColumnIndex = arraySubTypesByColumnIndex;
this.arraySubTypesByColumnName = arraySubTypesByColumnName;
this.targetBatchSize = targetBatchSize;
@@ -244,6 +253,13 @@ public final class JdbcToArrowConfig {
}
/**
+ * Get whether it is allowed to reuse the vector schema root.
+ */
+ public boolean isReuseVectorSchemaRoot() {
+ return reuseVectorSchemaRoot;
+ }
+
+ /**
* Gets the mapping between JDBC type information to Arrow type.
*/
public Function<JdbcFieldInfo, ArrowType> getJdbcToArrowTypeConverter() {
diff --git
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java
index cf08735..3941d97 100644
---
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java
+++
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigBuilder.java
@@ -34,6 +34,7 @@ public class JdbcToArrowConfigBuilder {
private Calendar calendar;
private BufferAllocator allocator;
private boolean includeMetadata;
+ private boolean reuseVectorSchemaRoot;
private Map<Integer, JdbcFieldInfo> arraySubTypesByColumnIndex;
private Map<String, JdbcFieldInfo> arraySubTypesByColumnName;
@@ -49,6 +50,7 @@ public class JdbcToArrowConfigBuilder {
this.allocator = null;
this.calendar = null;
this.includeMetadata = false;
+ this.reuseVectorSchemaRoot = false;
this.arraySubTypesByColumnIndex = null;
this.arraySubTypesByColumnName = null;
}
@@ -76,6 +78,7 @@ public class JdbcToArrowConfigBuilder {
this.allocator = allocator;
this.calendar = calendar;
this.includeMetadata = false;
+ this.reuseVectorSchemaRoot = false;
this.targetBatchSize = DEFAULT_TARGET_BATCH_SIZE;
}
@@ -172,6 +175,11 @@ public class JdbcToArrowConfigBuilder {
return this;
}
+ public JdbcToArrowConfigBuilder setReuseVectorSchemaRoot(boolean
reuseVectorSchemaRoot) {
+ this.reuseVectorSchemaRoot = reuseVectorSchemaRoot;
+ return this;
+ }
+
/**
* This builds the {@link JdbcToArrowConfig} from the provided
* {@link BufferAllocator} and {@link Calendar}.
@@ -184,6 +192,7 @@ public class JdbcToArrowConfigBuilder {
allocator,
calendar,
includeMetadata,
+ reuseVectorSchemaRoot,
arraySubTypesByColumnIndex,
arraySubTypesByColumnName,
targetBatchSize,
diff --git
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/AbstractJdbcToArrowTest.java
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/AbstractJdbcToArrowTest.java
index 6bbe098..c3cd457 100644
---
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/AbstractJdbcToArrowTest.java
+++
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/AbstractJdbcToArrowTest.java
@@ -63,6 +63,7 @@ public abstract class AbstractJdbcToArrowTest {
protected Connection conn = null;
protected Table table;
+ protected boolean reuseVectorSchemaRoot;
/**
* This method creates Table object after reading YAML file.
diff --git
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java
index 9682f65..68a681b 100644
---
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java
+++
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/JdbcToArrowConfigTest.java
@@ -116,13 +116,15 @@ public class JdbcToArrowConfigTest {
config = new JdbcToArrowConfigBuilder(allocator, calendar, true).build();
assertTrue(config.shouldIncludeMetadata());
- config = new JdbcToArrowConfig(allocator, calendar, true, null,
- null, JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE, null);
+ config = new JdbcToArrowConfig(allocator, calendar, /* include metadata */
true,
+ /* reuse vector schema root */ true, null, null,
JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE, null);
assertTrue(config.shouldIncludeMetadata());
+ assertTrue(config.isReuseVectorSchemaRoot());
- config = new JdbcToArrowConfig(allocator, calendar, false, null,
- null, JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE, null);
+ config = new JdbcToArrowConfig(allocator, calendar, /* include metadata */
false,
+ /* reuse vector schema root */ false, null, null,
JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE, null);
assertFalse(config.shouldIncludeMetadata());
+ assertFalse(config.isReuseVectorSchemaRoot());
}
@Test
diff --git
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowTest.java
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowTest.java
index 5957eee..ca1c0c0 100644
---
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowTest.java
+++
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowTest.java
@@ -67,6 +67,8 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.arrow.adapter.jdbc.AbstractJdbcToArrowTest;
import org.apache.arrow.adapter.jdbc.ArrowVectorIterator;
@@ -97,7 +99,6 @@ import org.apache.arrow.vector.types.pojo.Schema;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
/**
* JUnit Test Class which contains methods to test JDBC to Arrow data
conversion functionality with various data types
@@ -112,9 +113,11 @@ public class JdbcToArrowTest extends
AbstractJdbcToArrowTest {
* Constructor which populates the table object for each test iteration.
*
* @param table Table object
+ * @param reuseVectorSchemaRoot A flag indicating if we should reuse vector
schema roots.
*/
- public JdbcToArrowTest(Table table) {
+ public JdbcToArrowTest(Table table, boolean reuseVectorSchemaRoot) {
this.table = table;
+ this.reuseVectorSchemaRoot = reuseVectorSchemaRoot;
}
/**
@@ -125,9 +128,10 @@ public class JdbcToArrowTest extends
AbstractJdbcToArrowTest {
* @throws ClassNotFoundException on error
* @throws IOException on error
*/
- @Parameters
+ @Parameterized.Parameters(name = "table = {0}, reuse batch = {1}")
public static Collection<Object[]> getTestData() throws SQLException,
ClassNotFoundException, IOException {
- return Arrays.asList(prepareTestData(testFiles, JdbcToArrowTest.class));
+ return Arrays.stream(prepareTestData(testFiles,
JdbcToArrowTest.class)).flatMap(row ->
+ Stream.of(new Object[] {row[0], true}, new Object[] {row[0],
false})).collect(Collectors.toList());
}
/**
@@ -156,7 +160,8 @@ public class JdbcToArrowTest extends
AbstractJdbcToArrowTest {
@Test
public void testJdbcSchemaMetadata() throws SQLException {
- JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(new
RootAllocator(0), Calendar.getInstance(), true).build();
+ JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(new
RootAllocator(0), Calendar.getInstance(), true)
+ .setReuseVectorSchemaRoot(reuseVectorSchemaRoot).build();
ResultSetMetaData rsmd =
conn.createStatement().executeQuery(table.getQuery()).getMetaData();
Schema schema = JdbcToArrowUtils.jdbcToArrowSchema(rsmd, config);
JdbcToArrowTestHelper.assertFieldMetadataMatchesResultSetMetadata(rsmd,
schema);
@@ -230,11 +235,17 @@ public class JdbcToArrowTest extends
AbstractJdbcToArrowTest {
int x = 0;
final int targetRows = 600000;
ResultSet rs = new FakeResultSet(targetRows);
- try (ArrowVectorIterator iter = JdbcToArrow.sqlToArrowVectorIterator(rs,
allocator)) {
+ JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(
+ allocator, JdbcToArrowUtils.getUtcCalendar(), /* include metadata */
false)
+ .setReuseVectorSchemaRoot(reuseVectorSchemaRoot).build();
+
+ try (ArrowVectorIterator iter = JdbcToArrow.sqlToArrowVectorIterator(rs,
config)) {
while (iter.hasNext()) {
VectorSchemaRoot root = iter.next();
x += root.getRowCount();
- root.close();
+ if (!reuseVectorSchemaRoot) {
+ root.close();
+ }
}
} finally {
allocator.close();
@@ -618,7 +629,7 @@ public class JdbcToArrowTest extends
AbstractJdbcToArrowTest {
@Override
public boolean isAfterLast() throws SQLException {
- return false;
+ return numRows < 0;
}
@Override
diff --git
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowVectorIteratorTest.java
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowVectorIteratorTest.java
index edd1952..6206ddc 100644
---
a/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowVectorIteratorTest.java
+++
b/java/adapter/jdbc/src/test/java/org/apache/arrow/adapter/jdbc/h2/JdbcToArrowVectorIteratorTest.java
@@ -27,6 +27,7 @@ import static
org.apache.arrow.adapter.jdbc.JdbcToArrowTestHelper.getIntValues;
import static
org.apache.arrow.adapter.jdbc.JdbcToArrowTestHelper.getLongValues;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -77,9 +78,10 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
* Constructor which populates the table object for each test iteration.
*
* @param table Table object
+ * @param reuseVectorSchemaRoot A flag indicating if we should reuse vector
schema roots.
*/
- public JdbcToArrowVectorIteratorTest(Table table) {
- super(table);
+ public JdbcToArrowVectorIteratorTest(Table table, boolean
reuseVectorSchemaRoot) {
+ super(table, reuseVectorSchemaRoot);
}
@Test
@@ -96,6 +98,42 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
}
@Test
+ public void testVectorSchemaRootReuse() throws SQLException, IOException {
+
+ JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(new
RootAllocator(Integer.MAX_VALUE),
+
Calendar.getInstance()).setTargetBatchSize(3).setReuseVectorSchemaRoot(reuseVectorSchemaRoot).build();
+
+ ArrowVectorIterator iterator =
+
JdbcToArrow.sqlToArrowVectorIterator(conn.createStatement().executeQuery(table.getQuery()),
config);
+
+ int batchCount = 0;
+ VectorSchemaRoot prev = null;
+ while (iterator.hasNext()) {
+ VectorSchemaRoot cur = iterator.next();
+ assertNotNull(cur);
+
+ if (prev != null) {
+ // skip the first iteration
+
+ if (reuseVectorSchemaRoot) {
+ // when reuse is enabled, different iterations are based on the same
vector schema root.
+ assertTrue(prev == cur);
+ } else {
+ // when reuse is enabled, a new vector schema root is created in
each iteration.
+ assertFalse(prev == cur);
+ cur.close();
+ }
+ }
+
+ prev = cur;
+ batchCount += 1;
+ }
+
+ // make sure we have at least two batches, so the above test paths are
actually covered
+ assertTrue(batchCount > 1);
+ }
+
+ @Test
public void testJdbcToArrowValuesNoLimit() throws SQLException, IOException {
JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(new
RootAllocator(Integer.MAX_VALUE),
@@ -113,7 +151,7 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
// first experiment, with calendar and time zone.
JdbcToArrowConfig config = new JdbcToArrowConfigBuilder(new
RootAllocator(Integer.MAX_VALUE),
- Calendar.getInstance()).setTargetBatchSize(3).build();
+
Calendar.getInstance()).setTargetBatchSize(3).setReuseVectorSchemaRoot(reuseVectorSchemaRoot).build();
assertNotNull(config.getCalendar());
try (ArrowVectorIterator iterator =
@@ -127,7 +165,7 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
// second experiment, without calendar and time zone.
config = new JdbcToArrowConfigBuilder(new RootAllocator(Integer.MAX_VALUE),
- null).setTargetBatchSize(3).build();
+
null).setTargetBatchSize(3).setReuseVectorSchemaRoot(reuseVectorSchemaRoot).build();
assertNull(config.getCalendar());
try (ArrowVectorIterator iterator =
@@ -164,6 +202,7 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
while (iterator.hasNext()) {
VectorSchemaRoot root = iterator.next();
roots.add(root);
+
JdbcToArrowTestHelper.assertFieldMetadataIsEmpty(root);
bigIntVectors.add((BigIntVector) root.getVector(BIGINT));
@@ -397,7 +436,8 @@ public class JdbcToArrowVectorIteratorTest extends
JdbcToArrowTest {
@Test
public void testJdbcToArrowCustomTypeConversion() throws SQLException,
IOException {
JdbcToArrowConfigBuilder builder = new JdbcToArrowConfigBuilder(new
RootAllocator(Integer.MAX_VALUE),
-
Calendar.getInstance()).setTargetBatchSize(JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE);
+
Calendar.getInstance()).setTargetBatchSize(JdbcToArrowConfig.NO_LIMIT_BATCH_SIZE)
+ .setReuseVectorSchemaRoot(reuseVectorSchemaRoot);
// first experiment, using default type converter
JdbcToArrowConfig config = builder.build();