Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize bulk updates of custom field values when custom fields are added/removed #18980

Open
jeremystretch opened this issue Mar 21, 2025 · 0 comments · May be fixed by #18983
Open

Optimize bulk updates of custom field values when custom fields are added/removed #18980

jeremystretch opened this issue Mar 21, 2025 · 0 comments · May be fixed by #18983
Assignees
Labels
complexity: medium Requires a substantial but not unusual amount of effort to implement status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application

Comments

@jeremystretch
Copy link
Member

NetBox version

v4.2.5

Feature type

Change to existing functionality

Proposed functionality

This FR intends to capture an opportunity to improve performance when a custom field is added to or removed from a model which has many thousands of records. Whenever a custom field is added, its populate_initial_data() method is called to automatically populate the field's default value on all objects:

def populate_initial_data(self, content_types):
"""
Populate initial custom field data upon either a) the creation of a new CustomField, or
b) the assignment of an existing CustomField to new object types.
"""
for ct in content_types:
model = ct.model_class()
instances = model.objects.exclude(**{'custom_field_data__contains': self.name})
for instance in instances:
instance.custom_field_data[self.name] = self.default
model.objects.bulk_update(instances, ['custom_field_data'], batch_size=100)

The current approach is suboptimal, as it requires loading each individual object into memory to effect the change. I believe we can optimize this by mutating the JSON data directly within the query:

from django.db.models import F, Func, Value
from django.db.models import JSONField

def bulk_update_cf_value(model, field_name, new_value):
    model.objects.update(
        custom_field_data=Func(
            F('custom_field_data'),
            Value([field_name]),
            Value(new_value, JSONField()),
            function='jsonb_set'
        )
    )

bulk_update_cf_value(Site, "test1", "abc123")

This allows us to update the value of a specific key for all objects without first loading each into memory.

Similar approaches will be needed for the remove_stale_data() and rename_object_data() methods on CustomField as well.

Use case

This should result in a dramatic reduction in the time required to bulk update custom field data, particularly when many thousands of records are affected.

Database changes

N/A

External dependencies

N/A

@jeremystretch jeremystretch added complexity: medium Requires a substantial but not unusual amount of effort to implement status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application labels Mar 21, 2025
@jeremystretch jeremystretch self-assigned this Mar 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
complexity: medium Requires a substantial but not unusual amount of effort to implement status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application
Projects
None yet
1 participant