если `prop_id` in (1,2,3,...) штук 20, может быть и больше, запрос выполняется 18 секунд, что прям совсем много.
Критичное количество значений в таком списке - порядка 7..10, дальше действительно запрос резко замедляется.
Workaround: создаём индексированную временную таблицу в памяти, записываем в неё набор значений, используем в запросе:
CREATE TEMPORARY TABLE criteria (prop_id INT PRIMARY KEY) ENGINE = Memory
SELECT prop_id FROM (VALUES ROW(1), ROW(2), ROW(3), ...) criteria (prop_id);
и потом
select `product_id`, count(*) as `cnt`
from `product_prop`
NATURAL JOIN criteria
group by `product_id`
order by `cnt` desc
Ну а ускорить ORDER BY по вычисляемому полю - вообще без шансов.