Вот как эта задача решалась бы в СУБД с поддержкой аналитических функций:
SELECT group_id, order_id, value
FROM(
SELECT *, ROW_NUMBER()OVER(PARTITION BY group_id ORDER BY order_id) RowNum
FROM TestTable
)T
WHERE RowNum <= 2;
Однако оптимизатор MySQL ничего не знает о том, по каким правилам мы вычисляем поле RowNum. Ему придётся пронумеровать ВСЕ строки, и только потом отобрать нужные.
Теперь представьте, что у нас 1 миллион записей и 20 уникальных значений group_id. Т.е. чтобы выбрать 40 строк, MySQL будет вычислять значение RowNum для миллиона строк!
Фраза построена так, что создается впечатление, что только в MySQL будет идти перебор всех строк, а в других СУБД с поддержкой аналитических функций всё ok.
Разве row_number() в других СУБД не будет нумеровать все строки для указанного примера?
Статья хорошая, 10 лет назад внимательно читал бы примеры. Сейчас же, имхо, «старики» уже давно написали свои реализации, а новичкам есть решения из коробки.
По существу: утверждение «Красивого решения этой задачи одним запросом в MySQL нет.» устарело. LATERAL как раз и реализует, описанный ниже вариант, только в рамках одного запроса.
NOWAIT and SKIP LOCKED — Запретить запросу ждать блокировку на уровне таблицы и на уровне отдельных строк, соответственно.
Неудачная формулировка. Создается впечатление, что NOWAIT относится к уровню таблицы, а SKIP LOCKED — строк. Это не так.
SKIP LOCKED используюется для не детерминистического чтения из таблицы с пропуском строк, заблокированых другими пользователями.
NOWAIT — при наличии заблокированной строки не ждать освобождения блокировки innodb_lock_wait_timeout секунд, а сразу завершить выполнение запроса и вернуть ошибку:
ERROR 3572 (HY000): Do not wait for lock.
Есть хорошая статья Мартина Ханссона, перевод тут.
Зависит от запроса. Если используется алгоритм MERGE, то будут. Сравните explain итогового запроса через таблицу и запроса через представление, увидите их полную идентичность.
Вообще-то в черновом варианте даже написал про FOR UPDATE и LOCK IN SHARE MODE, но потом решил что в отрыве от InnoDB, а соответственно и транзакций с их уровнями изоляций это будет не в тему. Всё-таки эта статья предназначена для новичков, чтобы было понимание, что такое блокировки и с чем их едят, а уже потом можно рассматривать особенности различных механизмов хранения.
Фраза построена так, что создается впечатление, что только в MySQL будет идти перебор всех строк, а в других СУБД с поддержкой аналитических функций всё ok.
Разве row_number() в других СУБД не будет нумеровать все строки для указанного примера?
По существу: утверждение «Красивого решения этой задачи одним запросом в MySQL нет.» устарело. LATERAL как раз и реализует, описанный ниже вариант, только в рамках одного запроса.
SKIP LOCKED используюется для не детерминистического чтения из таблицы с пропуском строк, заблокированых другими пользователями.
NOWAIT — при наличии заблокированной строки не ждать освобождения блокировки innodb_lock_wait_timeout секунд, а сразу завершить выполнение запроса и вернуть ошибку:
ERROR 3572 (HY000): Do not wait for lock.
Есть хорошая статья Мартина Ханссона, перевод тут.
Во-вторых, для совместимости с приложениями, когда они требуют определенной структуры данных.
Вообще-то в черновом варианте даже написал про FOR UPDATE и LOCK IN SHARE MODE, но потом решил что в отрыве от InnoDB, а соответственно и транзакций с их уровнями изоляций это будет не в тему. Всё-таки эта статья предназначена для новичков, чтобы было понимание, что такое блокировки и с чем их едят, а уже потом можно рассматривать особенности различных механизмов хранения.