Poskytování velmi opožděné aktualizace této otázky:
Nenašel jsem příčinu, ale ukázalo se, že EXPLAIN byl jiný v PHP než v CLI. Nejsem si jistý, zda by nějaký aspekt připojení způsobil, že by se MySQL rozhodlo použít pro index jiné pole, protože pokud vím, tyto věci by spolu neměly souviset; ale bohužel, PHP EXPLAIN ukázalo, že nebyl použit správný index, zatímco CLI ano.
Řešením v tomto (zmateném) případě je použití hinting indexu . Viz řádek 'FROM' v tomto upraveném dotazu z mého příkladu:
SELECT HEX(al.uuid) hexUUID, al.created_on,
IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id,
pp.products_id product_id, al.action_id, al.last_updated
FROM ActionAPI.actionLists al USE INDEX (created_on)
LEFT JOIN ActionAPI.publishers_products pp
ON al.publisher_product_id = pp.id
WHERE (al.test IS NULL OR al.test = 0)
AND (al.created_on >= :since OR al.last_updated >= :since)
ORDER BY created_on ASC
LIMIT :skip, 100;
Doufám, že to někomu pomůže!