Проблемы и их решение в вопросе 1 обсуждаются в http://mysql.rjweb.org/doc.php/pagination
, в котором настоятельно рекомендуется «запомнить, где вы остановились» вместо OFFSET
, что обеспечивает значительное улучшение производительности. Он избавляется от $ID_list
и позволяет вам сделать два SELECTs
как один (что является еще одним преимуществом в производительности). (Ваше 8-кратное улучшение произошло из-за комбинации выбора нескольких столбцов и пропуска строк (OFFSET
).)
Вопрос 2 сложнее, так как вы хотите сделать несколько подсчетов. Попробуйте использовать GROUP BY
и COUNT(*)
, чтобы получить все значения в одном запросе. Риск состоит в том, что для этого может потребоваться столько данных (например, всех строк 5М), что это займет «слишком много времени». В тех немногих случаях, когда доступен «покрывающий» индекс, он не может быть «слишком длинным».
Вы могли бы делать большие групповые переходы каждую ночь - подсчитывает по марке и нет фильтрация, рассчитывается по модельному году и без фильтрации и т. д. c. Храните их в таблице для быстрой загрузки. Как только вы добавляете фильтрацию, сложность делает это непрактичным. Примечание: выполнение такого ночного подсчета подразумевает, что вы анализируете запрос пользователя, чтобы адаптировать SELECT
.
Даже счетчик-сколько-сколько-ряд-мы-о-на-страницу-через (вопроса 1) может быть слишком дорогостоящим.
См. здесь, как отделить «общие» атрибуты от «редких»: http://mysql.rjweb.org/doc.php/eav. Это приводит к нескольким составным запросам из 2-3 столбцов для обработки большинства из SELECT
от людей со случайными критериями фильтрации.
Уменьшите размер таблицы, используя минимальные типы данных , Model_year может использовать 2-байтовый тип данных YEAR
. Auto_in c для автомобилей 5M может использовать 3-байтовый MEDIUMINT UNSIGNED
(предел 16M).
Нормализация (замена длинной строки коротким идентификатором) экономит место, но, вероятно, будет стоить слишком дорого, если запросы фильтруются по нескольким критериям. Например: make = 'Ford' AND model = 'F150'
.
AND
относительно легко оптимизировать в предложении WHERE
; IN
хуже, а OR
еще хуже. В некоторых случаях IN
и OR
вам, возможно, придется прибегнуть к UNION
, чтобы избавиться от них. Пример:
( SELECT ... WHERE make = 'BMW' )
UNION ALL
( SELECT ... WHERE make = 'Audi' )
В ряде других случаев вам действительно нужно «построить» запрос в коде приложения, а не просто надеяться, что MySQL сможет сделать что-то оптимальное.
Выше UNION
не допускает нумерацию страниц; см. мои ссылки о том, как бороться с такими.