When ipb_range_start and ipb_range_end were introduced in https://static-codereview.wikimedia.org/MediaWiki/11887.html, they were set to an empty string for single-IP blocks. Identifying ranges which contain a given IP requires scanning, so removing single-IP blocks from the part of the index inhabited by range blocks reduced the amount of scanning which needed to occur.
This was accidentally broken in https://static-codereview.wikimedia.org/MediaWiki/17865.html / https://static-codereview.wikimedia.org/MediaWiki/17866.html, where a call to wfRangeStartEnd(), which rejected single IPs, was replaced with IP::parseRange(), which accepts single IPs.
We now have about 80,000 single-IP blocks on en.wp. 13,000 of them still have an empty ipb_range_start, presumably created before https://static-codereview.wikimedia.org/MediaWiki/17866.html (all have infinite expiry). The amount of table scanning is proportional to the number of blocks in the user's /16 range: 18 /16 ranges have more than 500 blocks, 61 have more than 100 blocks. The problem may well get worse as IPv6 becomes more common: the IPv6 code also uses a /16 division of index space.
ApiQueryBlocks now depends on the fact that ipb_range_start is populated, and so won't correctly display the 13,000 old blocks. Possibly there is other code that makes the same assumption. Such code should be fixed.
Version: 1.22.0
Severity: normal