Единственная независящая от программиста причина, по которой PDO будет жрать память, это
буферизованные по умолчанию запросы. поэтому если перед выполнением запроса написать
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, FALSE);
То ошибка исчезнет.
Остальные рекомендации настолько очевидны, что я постеснялся их писать сначала.
1. При выборке большого объема данных fetchAll() использовать
не рекомендуется.
2. Если все же хотим использовать, то надо убрать двойное заполнение массива
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
Все остальные претензии по памяти предъявлять РНР и собственному коду.