The polymorphic ipb_address field can contain an IP address, an IP range in CIDR notation, or a username. The username case is one of the few places that missed out on actor migration, so updating it is still required when users are renamed.
Direct references to ipb_address are rare in core and extensions. It would be simple to stop reading this field for user blocks. Then we could stop updating it and a script could blank it for user-block related rows.
The Block interface does expose ipb_address as Block::getTargetName(), but internally it is already discriminated, with a user block being stored as a UserIdentity.
DatabaseBlock::initFromRow() calls AbstractBlock::setTarget() with ipb_address which calls BlockUtils::parseBlockTarget() which converts the string to a UserIdentity. Instead DatabaseBlock::initFromRow() would make a UserIdentity from ipb_user, optionally joined on actor for the name, and would pass the UserIdentity to setTarget().
Special:BlockList does not sort by ipb_address, and searches are already aware of the target type.
ApiQueryBlocks searches ipb_address for user input, so will need to parse its input.