From 7e69d266f61a4b1190ae58143d755152430b6a71 Mon Sep 17 00:00:00 2001 From: Gus Brodman Date: Tue, 15 Sep 2026 15:52:20 -0400 Subject: [PATCH] Add a hibernate.default_batch_fetch_size value of 50 This basically controls the number of child entities that will be batch-loaded when we bulk-load multiple root entities. It will be useful for situations like RDE where we load a bunch of domains, because it means we'll batch-load the child entities like nsHosts and gracePeriods. --- .../java/google/registry/config/RegistryConfig.java | 12 ++++++++++++ .../registry/config/RegistryConfigSettings.java | 1 + .../google/registry/config/files/default-config.yaml | 6 ++++++ .../registry/persistence/PersistenceModule.java | 3 +++ .../registry/persistence/PersistenceModuleTest.java | 12 ++++++++++++ 5 files changed, 34 insertions(+) diff --git a/core/src/main/java/google/registry/config/RegistryConfig.java b/core/src/main/java/google/registry/config/RegistryConfig.java index 76823c0d9f3..1263a4aa36b 100644 --- a/core/src/main/java/google/registry/config/RegistryConfig.java +++ b/core/src/main/java/google/registry/config/RegistryConfig.java @@ -1825,6 +1825,18 @@ public static String getHibernateJdbcFetchSize() { return CONFIG_SETTINGS.get().hibernate.jdbcFetchSize; } + /** + * Returns the Hibernate default batch fetch size ({@code hibernate.default_batch_fetch_size}). + * + *

This controls the maximum number of uninitialized child entities or collection proxies that + * Hibernate will batch together into a single {@code SELECT ... WHERE id IN (...)} query when + * loading / initializing child entities in the persistence context. This is not the standard + * "batch size" used when loading root entities in batches. + */ + public static int getHibernateDefaultBatchFetchSize() { + return CONFIG_SETTINGS.get().hibernate.defaultBatchFetchSize; + } + /** Returns the roid suffix to be used for the roids of all hosts. */ public static String getHostRoidSuffix() { return CONFIG_SETTINGS.get().registryPolicy.contactAndHostRoidSuffix; diff --git a/core/src/main/java/google/registry/config/RegistryConfigSettings.java b/core/src/main/java/google/registry/config/RegistryConfigSettings.java index 1cdf2540080..bb71e9c85c7 100644 --- a/core/src/main/java/google/registry/config/RegistryConfigSettings.java +++ b/core/src/main/java/google/registry/config/RegistryConfigSettings.java @@ -130,6 +130,7 @@ public static class Hibernate { public String hikariIdleTimeout; public int jdbcBatchSize; public String jdbcFetchSize; + public int defaultBatchFetchSize; } /** Configuration for Cloud SQL. */ diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml index 9370aa6b30a..4b6fa7bda0e 100644 --- a/core/src/main/java/google/registry/config/files/default-config.yaml +++ b/core/src/main/java/google/registry/config/files/default-config.yaml @@ -247,6 +247,12 @@ hibernate: # database cursor. Here we set a small default geared toward Nomulus server # transactions. Large queries can override the defaults on a per-query basis. jdbcFetchSize: 40 + # The default batch fetch size is the maximum number of uninitialized child + # entities or collection proxies that Hibernate will load / initialize in a + # single batched SELECT query using an IN clause. This is not the same as the + # JDBC batch size, which controls batched insertions / updates of root + # entities. + defaultBatchFetchSize: 50 cloudSql: # jdbc url for the Cloud SQL database. diff --git a/core/src/main/java/google/registry/persistence/PersistenceModule.java b/core/src/main/java/google/registry/persistence/PersistenceModule.java index 9c5844fe106..bad95831357 100644 --- a/core/src/main/java/google/registry/persistence/PersistenceModule.java +++ b/core/src/main/java/google/registry/persistence/PersistenceModule.java @@ -17,6 +17,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.config.RegistryConfig.getHibernateConnectionIsolation; +import static google.registry.config.RegistryConfig.getHibernateDefaultBatchFetchSize; import static google.registry.config.RegistryConfig.getHibernateHikariConnectionTimeout; import static google.registry.config.RegistryConfig.getHibernateHikariIdleTimeout; import static google.registry.config.RegistryConfig.getHibernateHikariMaximumPoolSize; @@ -84,6 +85,7 @@ public abstract class PersistenceModule { public static final String JDBC_BATCH_SIZE = "hibernate.jdbc.batch_size"; public static final String JDBC_FETCH_SIZE = "hibernate.jdbc.fetch_size"; + public static final String DEFAULT_BATCH_FETCH_SIZE = "hibernate.default_batch_fetch_size"; @VisibleForTesting @Provides @@ -113,6 +115,7 @@ public static ImmutableMap provideDefaultDatabaseConfigs() { properties.put(Environment.DIALECT, NomulusPostgreSQLDialect.class.getName()); properties.put(JDBC_BATCH_SIZE, Integer.toString(getHibernateJdbcBatchSize())); properties.put(JDBC_FETCH_SIZE, getHibernateJdbcFetchSize()); + properties.put(DEFAULT_BATCH_FETCH_SIZE, Integer.toString(getHibernateDefaultBatchFetchSize())); return properties.build(); } diff --git a/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java b/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java index 3b7d7984cde..7fa38558262 100644 --- a/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java +++ b/core/src/test/java/google/registry/persistence/PersistenceModuleTest.java @@ -15,7 +15,11 @@ package google.registry.persistence; import static com.google.common.truth.Truth.assertThat; +import static google.registry.persistence.PersistenceModule.DEFAULT_BATCH_FETCH_SIZE; +import static google.registry.persistence.PersistenceModule.JDBC_BATCH_SIZE; +import static google.registry.persistence.PersistenceModule.JDBC_FETCH_SIZE; +import com.google.common.collect.ImmutableMap; import dagger.Component; import google.registry.config.CredentialModule; import google.registry.config.RegistryConfig.Config; @@ -77,6 +81,14 @@ void connectionIsolation() { .isEqualTo(TransactionIsolationLevel.TRANSACTION_SERIALIZABLE.name()); } + @Test + void batchAndFetchConfigs() { + ImmutableMap configs = PersistenceModule.provideDefaultDatabaseConfigs(); + assertThat(configs.get(JDBC_BATCH_SIZE)).isEqualTo("50"); + assertThat(configs.get(JDBC_FETCH_SIZE)).isEqualTo("40"); + assertThat(configs.get(DEFAULT_BATCH_FETCH_SIZE)).isEqualTo("50"); + } + @Singleton @Component( modules = {