Попробуйте так. Результат одинаковый будет, но оптимизатор не станет выполнять лишний select
SELECT `group_id` FROM `vkgroups` WHERE `group_id`
IN (SELECT `group_id` FROM `vkmembers` ORDER BY `members` DESC LIMIT 0,20)
Т.е. что вижу я тут странное. Вот это подзапрос, который в скобках. Он отбирает нечто, обратно это сортирует и берет первые 20 записей из результата.
Условно, значения у вас идут от 10 до 100 - берутся записи от 100 и до 80. Фактически - возьми последние 20 записей
SELECT `group_id` FROM `vkmembers` ORDER BY `members` DESC LIMIT 0,20
Зачем делать из этого потом еще один запрос select * - не ведаю.
И совершенно непонятно, зачем брать абсолютно все данные и их потом переворачивать. Добавьте, например, условие сюда же по дате, или брать не все данные, а половину только и скорость увеличится.