Can Core Data avoid index rebuild when adding a new attribute during lightweight migration?

I’m investigating Core Data lightweight migration behavior with SQLite and ran into a performance issue.

Scenario:

  • Model V1: EntityA has one fetchIndex

  • Model V2: EntityA adds a new optional attribute timestamp (Integer 64), with no changes to existing attributes or fetchIndex definitions

From a SQLite perspective, this change should be handled by a simple:

ALTER TABLE ZENTITYA ADD COLUMN ZTIMESTAMP INTEGER

But I observe that Core Data rebuilds the existing index, which becomes a significant performance issue for large databases.

CoreData: sql: DROP INDEX IF EXISTS Z_EntityA_id
CoreData: sql: ALTER TABLE ZENTITYA ADD COLUMN ZTIMESTAMP INTEGER
CoreData: sql: CREATE INDEX IF NOT EXISTS Z_EntityA_byID ON ZENTITYA

Question:

Is there any way to avoid or bypass index rebuilding for this kind of schema changes?

I don't see that Core Data provides any way for developers to customize the system-provided lightweight migration process, and so can only suggest that you file a feedback report – If you do so, please share your report ID here.

You might consider achieving your goal by migrating the data with your own code. That can be a bit involved though, depending on the complexity of your data set.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Thank you for the clarification. I’ve submitted FB22758653.

Regarding the suggestion to migrate the data with custom code, could you elaborate more on the approach?

Do you mean:

  1. Implementing a custom Core Data migration flow? My understanding is that fetch indexes may still be recreated because Core Data still detects the entity’s version hash change.
  2. Directly managing the underlying SQLite schema manually? If so, how would Core Data become compatible with the updated store afterward?

I’d appreciate any additional guidance on the recommended approach here.

Thanks for filing the report and following up here. I can't think of any way to avoid re-building the fetch index, but a custom migration process may help defer the work to a more appropriate timing, which may mitigate a bit the performance issue in the lightweight migration process.

Not sure if this is feasible in your case, but consider the following:

  1. In your model v2, keep EntityA unchanged, but create EntityA2 for EntityA + timestamp.
  2. Migrate the the existing v1 store to v2 with lightweight migration. EntityA doesn't have any change, and so the fetch index should be there.
  3. Copy the EntityA to EntityA2 in a more appropriate timing, and probably in the background.
  4. Do another migration to drop EntityA and use EntityA2 from then on.

This is far from ideal, and step 3 will still build fetch index, but you control how and when to run it.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Can Core Data avoid index rebuild when adding a new attribute during lightweight migration?
 
 
Q