Skip to content

Commit 70d1ccb

Browse files
Add index and reindex request settings to speed up reindex (#119780) (#119992)
- set slices:auto on the reindex request - set refresh_interval: -1 on destination index before reindexing into it - set number_of_replicas: 0 on destination index before reindexing into it - reset refresh_interval and number_of_replicas to previous value or default after reindex (cherry picked from commit c4024dc)
1 parent 6e90fd4 commit 70d1ccb

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

docs/changelog/119780.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 119780
2+
summary: Add index and reindex request settings to speed up reindex
3+
area: Data streams
4+
type: enhancement
5+
issues: []

x-pack/plugin/migrate/src/internalClusterTest/java/org/elasticsearch/xpack/migrate/action/ReindexDatastreamIndexTransportActionIT.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
1616
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
1717
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
18+
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateRequest;
19+
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteIndexTemplateAction;
1820
import org.elasticsearch.action.admin.indices.template.put.TransportPutComposableIndexTemplateAction;
1921
import org.elasticsearch.action.bulk.BulkRequest;
2022
import org.elasticsearch.action.bulk.BulkResponse;
@@ -155,7 +157,11 @@ public void testSettingsAddedBeforeReindex() throws Exception {
155157

156158
// update with a dynamic setting
157159
var numReplicas = randomIntBetween(0, 10);
158-
var dynamicSettings = Settings.builder().put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, numReplicas).build();
160+
var refreshInterval = randomIntBetween(1, 100) + "s";
161+
var dynamicSettings = Settings.builder()
162+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, numReplicas)
163+
.put(IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getKey(), refreshInterval)
164+
.build();
159165
indicesAdmin().updateSettings(new UpdateSettingsRequest(dynamicSettings, sourceIndex)).actionGet();
160166

161167
// call reindex
@@ -167,6 +173,7 @@ public void testSettingsAddedBeforeReindex() throws Exception {
167173
var settingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(destIndex)).actionGet();
168174
assertEquals(numReplicas, Integer.parseInt(settingsResponse.getSetting(destIndex, IndexMetadata.SETTING_NUMBER_OF_REPLICAS)));
169175
assertEquals(numShards, Integer.parseInt(settingsResponse.getSetting(destIndex, IndexMetadata.SETTING_NUMBER_OF_SHARDS)));
176+
assertEquals(refreshInterval, settingsResponse.getSetting(destIndex, IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getKey()));
170177
}
171178

172179
public void testMappingsAddedToDestIndex() throws Exception {
@@ -229,6 +236,38 @@ public void testReadOnlyAddedBack() {
229236
removeReadOnly(destIndex);
230237
}
231238

239+
public void testUpdateSettingsDefaultsRestored() {
240+
assumeTrue("requires the migration reindex feature flag", REINDEX_DATA_STREAM_FEATURE_FLAG.isEnabled());
241+
242+
// ESIntegTestCase creates a template random_index_template which contains a value for number_of_replicas.
243+
// Since this test checks the behavior of default settings, there cannot be a value for number_of_replicas,
244+
// so we delete the template within this method. This has no effect on other tests which will still
245+
// have the template created during their setup.
246+
assertAcked(
247+
indicesAdmin().execute(TransportDeleteIndexTemplateAction.TYPE, new DeleteIndexTemplateRequest("random_index_template"))
248+
);
249+
250+
var sourceIndex = randomAlphaOfLength(20).toLowerCase(Locale.ROOT);
251+
assertAcked(indicesAdmin().create(new CreateIndexRequest(sourceIndex)));
252+
253+
// call reindex
254+
var destIndex = client().execute(ReindexDataStreamIndexAction.INSTANCE, new ReindexDataStreamIndexAction.Request(sourceIndex))
255+
.actionGet()
256+
.getDestIndex();
257+
258+
var settingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(sourceIndex, destIndex)).actionGet();
259+
var destSettings = settingsResponse.getIndexToSettings().get(destIndex);
260+
261+
assertEquals(
262+
IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.getDefault(destSettings),
263+
IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(destSettings)
264+
);
265+
assertEquals(
266+
IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getDefault(destSettings),
267+
IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.get(destSettings)
268+
);
269+
}
270+
232271
public void testSettingsAndMappingsFromTemplate() throws IOException {
233272
assumeTrue("requires the migration reindex feature flag", REINDEX_DATA_STREAM_FEATURE_FLAG.isEnabled());
234273

x-pack/plugin/migrate/src/main/java/org/elasticsearch/xpack/migrate/action/ReindexDataStreamIndexTransportAction.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.action.admin.indices.readonly.AddIndexBlockRequest;
1515
import org.elasticsearch.action.admin.indices.readonly.AddIndexBlockResponse;
1616
import org.elasticsearch.action.admin.indices.readonly.TransportAddIndexBlockAction;
17+
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
1718
import org.elasticsearch.action.support.ActionFilters;
1819
import org.elasticsearch.action.support.HandledTransportAction;
1920
import org.elasticsearch.action.support.IndicesOptions;
@@ -25,6 +26,7 @@
2526
import org.elasticsearch.cluster.service.ClusterService;
2627
import org.elasticsearch.common.settings.Settings;
2728
import org.elasticsearch.core.TimeValue;
29+
import org.elasticsearch.index.IndexSettings;
2830
import org.elasticsearch.index.reindex.BulkByScrollResponse;
2931
import org.elasticsearch.index.reindex.ReindexAction;
3032
import org.elasticsearch.index.reindex.ReindexRequest;
@@ -95,6 +97,7 @@ protected void doExecute(
9597
.<AcknowledgedResponse>andThen(l -> deleteDestIfExists(destIndexName, l, taskId))
9698
.<AcknowledgedResponse>andThen(l -> createIndex(sourceIndex, destIndexName, l, taskId))
9799
.<BulkByScrollResponse>andThen(l -> reindex(sourceIndexName, destIndexName, l, taskId))
100+
.<AcknowledgedResponse>andThen(l -> copyOldSourceSettingsToDest(settingsBefore, destIndexName, l, taskId))
98101
.<AddIndexBlockResponse>andThen(l -> addBlockIfFromSource(WRITE, settingsBefore, destIndexName, l, taskId))
99102
.<AddIndexBlockResponse>andThen(l -> addBlockIfFromSource(READ_ONLY, settingsBefore, destIndexName, l, taskId))
100103
.andThenApply(ignored -> new ReindexDataStreamIndexAction.Response(destIndexName))
@@ -147,6 +150,8 @@ private void createIndex(
147150
var removeReadOnlyOverride = Settings.builder()
148151
.putNull(IndexMetadata.SETTING_READ_ONLY)
149152
.putNull(IndexMetadata.SETTING_BLOCKS_WRITE)
153+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
154+
.put(IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getKey(), -1)
150155
.build();
151156

152157
var request = new CreateIndexFromSourceAction.Request(
@@ -168,6 +173,7 @@ private void reindex(String sourceIndexName, String destIndexName, ActionListene
168173
reindexRequest.getSearchRequest().source().fetchSource(true);
169174
reindexRequest.setDestIndex(destIndexName);
170175
reindexRequest.setParentTask(parentTaskId);
176+
reindexRequest.setSlices(0); // equivalent to slices=auto in rest api
171177
client.execute(ReindexAction.INSTANCE, reindexRequest, listener);
172178
}
173179

@@ -186,6 +192,35 @@ private void addBlockIfFromSource(
186192
}
187193
}
188194

195+
private void copyOldSourceSettingsToDest(
196+
Settings settingsBefore,
197+
String destIndexName,
198+
ActionListener<AcknowledgedResponse> listener,
199+
TaskId parentTaskId
200+
) {
201+
logger.debug("Updating settings on destination index after reindex completes");
202+
203+
var settings = Settings.builder();
204+
copySettingOrUnset(settingsBefore, settings, IndexMetadata.SETTING_NUMBER_OF_REPLICAS);
205+
copySettingOrUnset(settingsBefore, settings, IndexSettings.INDEX_REFRESH_INTERVAL_SETTING.getKey());
206+
207+
var updateSettingsRequest = new UpdateSettingsRequest(settings.build(), destIndexName);
208+
updateSettingsRequest.setParentTask(parentTaskId);
209+
var errorMessage = String.format(Locale.ROOT, "Could not update settings on index [%s]", destIndexName);
210+
client.admin().indices().updateSettings(updateSettingsRequest, failIfNotAcknowledged(listener, errorMessage));
211+
}
212+
213+
private static void copySettingOrUnset(Settings settingsBefore, Settings.Builder builder, String setting) {
214+
// if setting was explicitly added to the source index
215+
if (settingsBefore.get(setting) != null) {
216+
// copy it back to the dest index
217+
builder.copy(setting, settingsBefore);
218+
} else {
219+
// otherwise, delete from dest index so that it loads from the settings default
220+
builder.putNull(setting);
221+
}
222+
}
223+
189224
public static String generateDestIndexName(String sourceIndex) {
190225
return "migrated-" + sourceIndex;
191226
}

0 commit comments

Comments
 (0)