Производительность |
||
Для начала сравним по производительности нумерацию строк в запросе с помощью самосоединения и с помощью переменных: 1) Классический способ с самомоединением:
Duration / Fetch 16.084 sec / 0.016 sec 2) С использованием переменных:
Duration / Fetch 0.016 sec / 0.015 sec Результат говорит сам за себя. Однако надо понимать, что вычисленные с помощью переменных значения не оптимально использовать в условиях фильтрации. Сортировка и вычисление будут происходить для ВСЕХ строк, несмотря на то, что в итоге нам нужна только малая их часть. Рассмотрим более подробно на примере такой задачи: Вывести по 2 первые строки из таблицы TestTable для каждого значения group_id, отсортированных по order_id. Вот как эта задача решалась бы в СУБД с поддержкой аналитических функций:
Поскольку СУБД «знает», как работает ROW_NUMBER, оптимизатору незачем нумеровать ВСЕ строки, чтобы выбрать первые две. И всё выполнится быстро (при наличии индекса по group_id, order_id, конечно). В случае с MySQL решение с подобным алгоритмом будет выглядеть так:
Однако оптимизатор MySQL ничего не знает о том, по каким правилам мы вычисляем поле RowNum. Ему придётся пронумеровать ВСЕ строки, и только потом отобрать нужные. Теперь представьте, что у нас 1 миллион записей и 20 уникальных значений group_id. Т.е. чтобы выбрать 40 строк, MySQL будет вычислять значение RowNum для миллиона строк! Красивого решения этой задачи одним запросом в MySQL нет. Но можно сначала получить список уникальных значений group_id, например, так:
Затем средствами любого другого языка программирования сгенерировать запрос вида:
20 лёгких запросов отработают намного быстрее, чем вычисление RowNum для миллиона строк. |