Ik geef een zeer late update over deze vraag:
Ik heb de oorzaak niet gevonden, maar het blijkt dat de EXPLAIN anders was in PHP dan in de CLI. Ik weet niet zeker of een aspect van de verbinding ervoor zou zorgen dat MySQL ervoor zou kiezen om een ander veld voor de index te gebruiken, want voor zover ik weet zouden die dingen geen verband moeten houden; maar helaas, PHP's EXPLAIN toonde aan dat de juiste index niet werd gebruikt, terwijl de CLI's dat wel deden.
De oplossing in dit (verbijsterende) geval is om indexhints te gebruiken . Zie de 'FROM'-regel in deze aangepaste query uit mijn voorbeeld:
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;
Ik hoop dat dit iemand helpt!