Как эффективно разбивать большие массивы данных на PHP и MySQL? - PullRequest
7 голосов
/ 01 сентября 2009

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

Например:

SELECT * FROM my_table LIMIT 10000, 20;

Означает, что MySQL по-прежнему будет читать первые 10000 записей и выбрасывать их до получения 20, которые нам нужны.

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

Кто-нибудь знает о каком-либо существующем классе / методике / методологии разбиения на страницы, которые могут разбивать большие массивы данных на более эффективные способы, т. Е. Которые не используют ключевое слово LIMIT MySQL?

В PHP, если это возможно, так как это оружие выбора в моей компании.

Приветствие.

Ответы [ 7 ]

7 голосов
/ 01 сентября 2009

Прежде всего, если вы хотите разбить на страницы, у вас обязательно должно быть предложение ORDER BY. Тогда вам просто нужно использовать это предложение, чтобы глубже копаться в вашем наборе данных. Например, рассмотрим это:

SELECT * FROM my_table ORDER BY id LIMIT 20

У вас будут первые 20 записей, скажем, их идентификаторы: 5,8,9, ..., 55,64. Ваша пагинационная ссылка на страницу 2 будет выглядеть как "list.php? Page = 2 & id = 64", а ваш запрос будет

SELECT * FROM my_table WHERE id > 64 ORDER BY id LIMIT 20

Нет смещения, прочитано только 20 записей. Это не позволяет вам произвольно переходить на любую страницу, но в большинстве случаев люди просто просматривают следующую / предыдущую страницу. Индекс «id» улучшит производительность даже при больших значениях OFFSET.

1 голос
/ 15 ноября 2010
SELECT * FROM my_table LIMIT 10000, 20;

означает, что в поиске будет показано 20 записей, начиная с записи # 10000, если при использовании первичных ключей в предложении where не будет большой нагрузки на мой sql

любые другие методы pagnation будут очень сильно загружены, как при использовании метода join

1 голос
/ 01 сентября 2009

Существует в основном 3 подхода к этому, каждый из которых имеет свои компромиссы:

  1. Отправка всех 10000 записей клиенту и обработка пагинации на стороне клиента через Javascript или тому подобное. Очевидное преимущество заключается в том, что для всех записей необходим только один запрос; очевидным недостатком является то, что если размер записи каким-либо образом значительным, размер страницы, отправляемой в браузер, будет пропорциональным размером - и пользователь может не заботиться о полном наборе записей.

  2. Делайте то, что вы в данный момент делаете, а именно SQL LIMIT, и получайте только те записи, которые вам нужны с каждым запросом, без сохранения состояния. Преимущество в том, что он отправляет записи только для страницы, запрашиваемой в данный момент, поэтому запросы небольшие, недостатки в том, что: а) требуется запрос к серверу для каждой страницы, и б) он медленнее, так как количество записей / страниц увеличивается для последующих страниц результат, как вы упомянули. Иногда может помочь использование оператора JOIN или WHERE в монотонно увеличивающемся поле id, особенно если вы запрашиваете результаты из статической таблицы, а не динамического запроса.

  3. Поддерживает некоторый объект состояния на сервере, который кэширует результаты запроса и может использоваться в будущих запросах в течение ограниченного периода времени. Недостатком является то, что он имеет лучшую скорость запросов, так как реальный запрос должен выполняться только один раз; недостатком является необходимость управлять / хранить / очищать эти объекты состояния (особенно неприятно для сайтов с большим трафиком).

1 голос
/ 01 сентября 2009

Решение может состоять в том, чтобы не использовать предложение limit, а вместо этого использовать соединение - объединение в таблице, используемой в качестве некоторой последовательности.

Для получения дополнительной информации о SO я нашел этот вопрос / ответ , в котором приведен пример - который может вам помочь; -)

0 голосов
/ 01 сентября 2009

некоторые другие опции,

  • Разделите таблицы на каждую страницу, поэтому игнорируйте ограничение
  • Сохранение результатов в сеансе (хорошей идеей было бы создать хеш этих данных с использованием md5, а затем использовать этот кеш для сеанса для нескольких пользователей)
0 голосов
/ 01 сентября 2009

Лучший способ - определить индексное поле в my_table, и для каждой новой вставленной строки необходимо увеличивать это поле. И в конце концов вам нужно использовать WHERE YOUR_INDEX_FIELD BETWEEN 10000 И 10020 Это будет намного быстрее.

0 голосов
/ 01 сентября 2009

Мне не известно о том снижении производительности, о котором вы упоминали, и я не знаю ни одного другого решения для разбивки на страницы, однако предложение ORDER BY может помочь вам сократить время загрузки.

...