When a group is deleted, it is "merged" into the Name_layer_special group by adding a redirection from the original group's ID to Name_layer_special's ID in the faction_id table.
Then, it deletes all members of the group. However, that breaks this statement which is an INNER JOIN, and only returns a row if there is a row in both tables.
Since the deleted group does not have any members, this query will not return the deleted group's ID, and that ID will not be associated with this group.
This caused a problem, because the deleted group's ID is still associated with all the reinforcements with that group. Whenever the group of a reinforcement is looked up, it will find the Name_layer_special group through the faction_id table's association. However, the lookup will not be cached, because the cache key is based on any IDs associated with the resultant group, and in this case, it does not include the deleted group's ID.
Therefore, with no caching, a database lookup will occur every time the group is needed, which will be performed on the main thread and can occur several times during, for instance, a single /cti or block break.
The fix involves using LEFT JOIN instead of INNER JOIN, so that the deleted group will still be returned even though it does not have any members.
This uses 0.5%-1% of a tick by copying loads of data around that we never use, this uses the new getHolder(boolean) method added by https://github.com/PaperMC/Paper/pull/3535, which is much faster.
- Sort all groups by their names
- Sort members of groups by their rank, and then their name
- Show /nlpp and /nlrm command hints (most people don't seem to be aware of these commands)