MySQL смещает бесконечные строки

Я хотел бы создать запрос, который отображает все результаты в таблице, но смещен на 5 от начала таблицы. Насколько я могу судить, MySQL LIMIT требует не только смещения, но и ограничения. Есть какой-либо способ сделать это?

Это совершенно правильный вопрос, но мне интересно, что было бы лучше - захватить все и программно проигнорировать первые несколько записей. Учитывая ужас того, что кажется лучшим ответом (предел 5, 18446744073709551615), я бы в значительной степени поддержал работу над ограничениями MySQL LIMIT.

cesoid 31.01.2015 05:31

@cesoid, а если вам нужен limit 5000, 18446744073709551615. Вы не собираетесь извлекать лишние 5000 строк только для того, чтобы ваш код выглядел красиво.

elipoultorak 26.10.2015 14:03

@ user3576887 Я думаю, что вы правы, я просто рассматривал вопрос выше, предполагая, что 5 является единственным требованием, а не какой-то переменной суммой, которая может быть намного больше (и вместо решения чьей-то проблемы).

cesoid 28.10.2015 17:29

Я предполагаю, что это настолько редкая задача, что можно смириться с безобразием решения.

Rick James 16.05.2017 02:16
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
117
4
66 863
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Как вы упомянули, требуется LIMIT, поэтому вам нужно использовать максимально возможный предел, который составляет 18446744073709551615 (максимум беззнакового BIGINT)

SELECT * FROM somewhere LIMIT 18446744073709551610 OFFSET 5

Вау, это официальное решение от команды MySQL?

Antony 23.05.2011 22:11

Интересно, почему люди до сих пор используют MySQL, когда есть PostgreSQL ...

Rodrigo 12.03.2021 00:39
Ответ принят как подходящий

Из Руководство MySQL по LIMIT:

To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:

SELECT * FROM tbl LIMIT 95, 18446744073709551615;

Ужасный! Я пришел сюда в надежде, что MySQL сделал предложение Limit необязательным, как есть, но также с предоставленным смещением ... но нет! Я видел этот разброс 18446744073709551615 по всему коду и обвинял ленивых программистов, но это особенность дизайна!

Petruza 24.05.2010 19:10

ужасный ответ, но это официальный документ из MySQL Doc. Что я могу сказать @_@

GusDeCooL 19.10.2011 22:06

18446744073709551615 - это 2 ^ 64-1 для тех, кому интересно. Вы можете быть осторожны, потому что вы не сможете сохранить это значение в виде 32-битного целого числа. Вы должны убедиться, что сохранили это как строку, чтобы обеспечить совместимость.

AlicanC 08.12.2011 02:51

Ужасный! они должны быть более элегантными, чем это ... Limit -1 или Limit Null выглядят довольно разумно! или, по крайней мере, Limit должен принимать подзапрос типа select * from table limit (select count(*) from table)

vulcan raven 16.01.2012 02:04

что я могу сказать .. я разочарован! это просто грязный обходной путь, и все же это единственный вариант :( Команда MySQL должна это исправить!

ioleo 05.07.2012 13:54

используйте php 'PHP_INT_MAX', чтобы избежать эффектов переполнения.

Karl Adler 07.04.2014 19:11

Я думаю, что это подпадает под категорию TODINAWYW, которую я только что придумал, и означает «Официальная документация - это не всегда то, что вам нужно». В нем объясняется, как вы могли бы получить все записи, если бы у вас была таблица, которая была заполнена до (примерно) 18 квинтиллионов строк, а также предлагалось использовать «некоторое большое число» в качестве альтернативы, но я бы предположил, что существует значимая, не- бесконечное и отличное от 18 квинтиллионов количество записей, которые вы хотите вернуть, и вы должны это использовать. (Я включил это в свой ответ.)

cesoid 29.07.2016 20:12

Похоже, что в MySQL есть некоторая особая обработка для 18446744073709551615. Это не принято в качестве LIMIT для предложения DELETE с включенным безопасным режимом, например. Однако 18446744073709551614 принимается.

stannius 24.05.2017 21:17

Это нелепо! Интересно, почему люди до сих пор используют MySQL, когда есть PostgreSQL ...

Rodrigo 12.03.2021 00:39

Другой подход - выбрать столбец с автоимкрементом, а затем отфильтровать его с помощью HAVING.

SET @a := 0; 
select @a:=@a + 1 AS counter, table.* FROM table 
HAVING counter > 4

Но я бы, вероятно, придерживался подхода высоких лимитов.

спасибо, и мне интересно, как я могу поместить такой запрос в оператор PHP! я имею в виду именно так $sql = 'SET @a :=0 SELECT .....';

Reham Fahmy 18.08.2018 01:57

Как раз сегодня я читал о том, как лучше всего получить огромные объемы данных (более миллиона строк) из таблицы mysql. Один из способов - использовать LIMIT x,y, где x - это смещение, а y - последняя строка, которую вы хотите вернуть. Однако, как я выяснил, это не самый эффективный способ сделать это. Если у вас есть столбец с автоинкрементом, вы можете легко использовать оператор SELECT с предложением WHERE, указывающим, с какой записи вы хотите начать.

Например, SELECT * FROM table_name WHERE id > x;

Кажется, что mysql получает все результаты, когда вы используете LIMIT, а затем показывает только те записи, которые соответствуют смещению: не самое лучшее для производительности.

Источник: Ответ на этот вопрос Форумы MySQL. Сразу обратите внимание, вопрос примерно 6 лет.

Это даст неверные результаты, если вы когда-либо удаляли запись. Этот метод особенно опасен, потому что он работает большую часть времени и тихо дает сбой, когда он не работает.

octern 15.04.2014 22:48

Я знаю, что это старый, но я не видел аналогичного ответа, поэтому я бы использовал это решение.

Во-первых, я бы выполнил запрос количества в таблице, чтобы увидеть, сколько записей существует. Этот запрос выполняется быстро и обычно время выполнения незначительно. Что-то типа:

SELECT COUNT(*) FROM table_name;

Затем я бы построил свой запрос, используя результат, который я получил от count, в качестве моего предела (поскольку это максимальное количество строк, которое таблица могла бы вернуть). Что-то типа:

SELECT * FROM table_name LIMIT count_result OFFSET desired_offset;

Или, возможно, что-то вроде:

SELECT * FROM table_name LIMIT desired_offset, count_result;

Конечно, при необходимости вы можете вычесть желаемое смещение из count_result, чтобы получить фактическое точное значение, которое будет использоваться в качестве предела. Передача значения «18446744073709551610» просто не имеет смысла, если я действительно могу определить подходящий предел для предоставления.

select count (*) в таблице с 7M записями занимает около 17 секунд

amd 21.05.2017 11:06
WHERE .... AND id > <YOUROFFSET>

id может быть любым автоматически увеличивающимся или уникальным числовым столбцом, который у вас есть ...

Плохая идея. Это даст неправильное смещение, если вы когда-либо удаляли строку.

octern 15.04.2014 22:49

Вы можете использовать оператор MySQL с LIMIT:

START TRANSACTION;
SET @my_offset = 5;
SET @rows = (SELECT COUNT(*) FROM my_table);
PREPARE statement FROM 'SELECT * FROM my_table LIMIT ? OFFSET ?';
EXECUTE statement USING @rows, @my_offset;
COMMIT;

Протестировано в MySQL 5.5.44. Таким образом, мы можем избежать вставки числа 18446744073709551615.

примечание: транзакция гарантирует, что переменная @rows соответствует таблице, учитываемой при выполнении оператора.

как указано в @amd: «select count (*) в таблице с 7M записями занимает около 17 секунд»

Rodrirokr 17.07.2020 22:35

Как отмечалось в других ответах, MySQL предлагает использовать 18446744073709551615 в качестве количества записей в пределе, но учтите следующее: что бы вы сделали, если бы получили обратно 18 446 744 073 709 551 615 записей? Фактически, что бы вы сделали, если бы у вас было 1 000 000 000 записей?

Может быть, вам действительно нужно более одного миллиарда записей, но я хочу сказать, что есть некоторый предел на число хочу, и оно меньше 18 квинтиллионов. Ради стабильности, оптимизации и, возможно, удобства использования, я бы предложил установить некоторые значимые ограничения на запрос. Это также уменьшит путаницу для тех, кто никогда не видел это волшебное число, и получит дополнительное преимущество в виде сообщения, по крайней мере, о том, сколько записей вы готовы обрабатывать одновременно.

Если вам действительно нужно получить все 18 квинтиллионов записей из вашей базы данных, возможно, вы действительно хотите получить их с шагом 100 миллионов и выполнить цикл 184 миллиарда раз.

Вы правы, но оставлять это решение разработчику - не лучший выбор.

amd 21.05.2017 11:04

@amd Не могли бы вы объяснить это поподробнее? Я не знаю, что вы пытаетесь сказать.

cesoid 22.05.2017 18:49

@cesoid Я думаю, он говорит, что разработчики не должны произвольно выбирать бизнес-логику, с чем я согласен, но только до определенной степени. Допустим, вы возвращаете клиенту список заказов. Совершенно разумно никогда не возвращать больше, скажем, миллиона за раз, но ограничение до 100 может вызвать путаницу.

Autumn Leonard 03.08.2018 23:15

@amd Я не говорю, что разработчик должен изменить поведение приложения, чтобы избежать использования 18446744073709551615. Я говорю, что им следует подумать, имеет ли смысл использовать это число как часть реализации того, что клиент или дизайнер интерфейса запросил, и вряд ли это будет правильная реализация для чего-либо. Решение использовать MySQL, вероятно, уже было принято разработчиком, не задаваясь вопросом, будет ли что-то более 18 квинтиллионов.

cesoid 10.07.2019 16:43

Как уже упоминалось, из руководства MySQL. Для этого вы можете использовать максимальное значение беззнакового большого int, то есть это ужасное число (18446744073709551615). Но чтобы сделать его немного менее беспорядочным, вы можете использовать побитовый оператор тильды "~".

  LIMIT 95, ~0

он работает как побитовое отрицание. Результат «~ 0»: 18446744073709551615.

Не работает в MariaDB 10.3 :( Я пробовал и LIMIT 5, ~0, и LIMIT ~0 OFFSET 5. Это функция MySQL 8.0?

jurchiks 09.12.2019 19:23

В MySQL 5.7 этого нет - неверный синтаксис.

Jonny Nott 26.02.2020 12:53

Другие вопросы по теме