Поскольку я не большой поклонник MySQL, я бы спросил, пробовали ли вы PostgreSQL. В этой БД вы хотели бы убедиться, что ваша настройка work_mem была достаточно высокой, но вы можете установить ее для каждого соединения с БД, например, SET work_mem = 64 МБ.
Еще одно предложение - изучить использование повторяющихся записей пути. - это множество URL-адресов с общими путями.
Еще одна вещь, которая может помочь, а может и не помочь, - это использовать текстовые поля фиксированной длины вместо varchars. Раньше это делало разницу в скорости, но я не уверен насчет современных двигателей DB.
Если вы используете PostgreSQL, это позволит вам использовать JOIN USING, но даже в MySQL мне это нравится больше: имя поля идентификатора должно быть одинаковым в каждой таблице. Вместо id в hosts и host в urls, назовите его host_id в обоих местах.
Теперь еще несколько комментариев. :)
Этот макет данных, который у вас есть, очень полезен, когда вы выбираете небольшой набор строк, возможно, каждый URL из одного домена. Это также может помочь lot , если ваши запросы часто требуют последовательного сканирования таблицы URL для других данных, хранящихся там, потому что сканирование может пропускать большие текстовые поля (если это не имеет значения, потому что БД хранит текст через указатели на связанную таблицу в любом случае).
Однако, если вы почти всегда выбираете все данные домена и пути, то имеет смысл хранить их в одной таблице.