Vous le faites correctement -- c'est juste lent, parce que l'abstraction supplémentaire de l'ORM signifie que vous ne pouvez pas faire le genre d'optimisations que vous voudriez.
Cela dit, EntityManager ralentit les transactions aussi importantes. Si vous n'en avez pas absolument besoin dans une seule grosse transaction, vous pouvez probablement obtenir un code plus performant en vidant() puis en effaçant() l'EM toutes les 20 à 200 itérations de votre boucle.
Si cela ne vous donne pas assez de performances, la seule alternative à laquelle je peux penser est de revenir au code personnalisé qui exécute le SQL personnalisé directement sur votre SGBD.
Je sais que ce n'est pas une bonne réponse, mais au moins je peux vous dire que vous n'êtes pas fou.
------ modifier ------
De l'article officiel de Doctrine2 sur Traitement par lots
:
Il existe également une différence significative de performances lors de l'utilisation de distant vs local base de données car la surcharge de l'envoi de chaque requête au serveur distant est assez importante. La surcharge est beaucoup plus faible lors de l'utilisation de la base de données locale grâce aux transactions et aux optimisations de la base de données. (par exemple 70sec abaissé à 300ms dans le cas de l'exemple dans la question)