Вот что я сделал, и сократил общее время выполнения в 10 раз.
Что я понял из плана выполнения моего исходного запроса, так это то, что он использовал сортировку файлов для сортировки всех результатов и игнорирования индексов. Это пустая трата.
Моя тестовая база данных: 5 млн записей, размер 20 ГБ. структура таблицы такая же, как в вопросе
Вместо того, чтобы получать blobCol непосредственно в первом запросе, я сначала получаю значение 'name' для начала каждой страницы. Запускайте этот запрос бесконечно, пока он не вернет 0 результатов Каждый раз добавлять результат в список
SELECT name
FROM my_table
where id = <anyId> // I use the id column for partitioning so I need this here
order by name
limit <pageSize * pageNumber>, 1
Номер страницы синуса ранее не известен, начинайте со значения 0 и продолжайте увеличивать, пока запрос не вернет значение NULL. Вы также можете сделать счетчик выбора (*), но это само по себе может занять много времени и не поможет ничего оптимизировать На выполнение каждого запроса уходило около 2 секунд, если номер страницы превышал ~ 60.
Для меня размер страницы был 5000, поэтому я получил список строк с именами в позициях 0, 5001, 10001, 15001 и так далее. Число страниц оказалось равным 1000, а сохранение списка из 1000 результатов в памяти не является дорогостоящим.
Теперь, переберите список и выполните этот запрос
SELECT blobCol
FROM my_table
where name >= <pageHeader>
and name < <nextPageHeader>
and city="<any string>"
and id= 1
Это будет выполнено N раз, где N = размер списка, полученного ранее. Поскольку «имя» является первичным ключом col, а «город» также индексируется, EXPLAIN показывает, что это вычисление выполняется в памяти с использованием индекса.
Теперь на выполнение каждого запроса уходит 1 секунда, а не 30-40. Таким образом, объединяя время предварительной обработки 2 секунды на страницу, общее время на страницу составляет 3-4 секунды вместо 30-40.
Если у кого-то есть лучшее решение или если с этим что-то явно не так, пожалуйста, дайте мне знать