bagadjan, я в таких случаях иногда делаю так -
Два запроса. Первым просто забираю интересующие меня айдишники, без остальных полей и всего чем можно пренебречь.
После делаю запрос только туда, куда надо с условием WHERE ID IN(...)
Попробуй, может быстрее получится.
Можно еще кэширование запроса сделать. Те же айдишники сохранять в отдельную таблицу строкой для каждого запроса. с определенным ttl, в зависимости от динамичности изменений твоей бд.
А tmp_table столько весит потому что я на сотку уверен, в product_categories связка один ко многим. Для этого ты и делаешь после группировку. Кстати, вложенный селект в этом запросе тебя бы от нее спас, если делать ...
INNER JOIN
(SELECT DISTINCT product_id FROM WHERE pc.category_id in('2') ) as prod_list ON prod_list.product_id = p.id