Skip to content

Commit 8bb47da

Browse files
authored
Fixes #20023: Add GiST index on Prefix.prefix for net contains ops (#20059)
Resolves performance issue where prefix deletion with 2000+ children took 5-10 minutes due to sequential scans in hierarchy depth/children calculations. Adding PostgreSQL GiST index with inet_ops enables efficient network containment operators (>>, <<, <<=) in annotate_hierarchy() queries. Performance impact: - 30-60x speedup: 5-10 minutes → 10 seconds for large prefix deletions - Real-world validation: 4s migration time on 1.24M prefix dataset - Storage cost: 47MB index (11% of table storage, 38 bytes per prefix) Works in conjunction with existing B-tree indexes on vrf_id for optimal query performance. Benefits all network containment operations including hierarchy navigation, aggregate views, and available IP/prefix calculations.
1 parent 5d7c831 commit 8bb47da

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from django.contrib.postgres.indexes import GistIndex
2+
from django.db import migrations
3+
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [
8+
('contenttypes', '0002_remove_content_type_name'),
9+
('dcim', '0210_macaddress_ordering'),
10+
('extras', '0129_fix_script_paths'),
11+
('ipam', '0081_remove_service_device_virtual_machine_add_parent_gfk_index'),
12+
('tenancy', '0020_remove_contactgroupmembership'),
13+
]
14+
15+
operations = [
16+
migrations.AddIndex(
17+
model_name='prefix',
18+
index=GistIndex(fields=['prefix'], name='ipam_prefix_gist_idx', opclasses=['inet_ops']),
19+
),
20+
]

netbox/ipam/models/ip.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import netaddr
22
from django.contrib.contenttypes.fields import GenericForeignKey
3+
from django.contrib.postgres.indexes import GistIndex
34
from django.core.exceptions import ValidationError
45
from django.db import models
56
from django.db.models import F
@@ -281,6 +282,13 @@ class Meta:
281282
ordering = (F('vrf').asc(nulls_first=True), 'prefix', 'pk') # (vrf, prefix) may be non-unique
282283
verbose_name = _('prefix')
283284
verbose_name_plural = _('prefixes')
285+
indexes = [
286+
GistIndex(
287+
fields=['prefix'],
288+
name='ipam_prefix_gist_idx',
289+
opclasses=['inet_ops'],
290+
),
291+
]
284292

285293
def __init__(self, *args, **kwargs):
286294
super().__init__(*args, **kwargs)

0 commit comments

Comments
 (0)