I've found over a period of years a zabbix-server + mysql combination will cause this query, which should be empty, to nevertheless find a dozen or so items corresponding to millions of orphaned history rows. Housekeeping runs complete without removing these.
select distinct(itemid) FROM `history` where itemid not in (SELECT itemid FROM `items`);
I could be missing some zabbix use case, zabbix is not my primary focus. Maybe there's a 'retired item' table somewhere. But if I'm not, for those of us who would rather have the database space than retain a history of deleted items, consider adding a housekeeping flag to delete such orphans automatically. Perhaps a database rule to cause item deletes to cascade delete related history entries?
Finally, my appreciation for creating and supporting such a useful tool!