PHP-разбиение на страницы MySQL со случайным упорядочением

Это проблема с заказом результатов поиска на моем веб-сайте,

Когда выполняется поиск, на странице контента появляются случайные результаты, на этой странице также отображается разбиение на страницы. Я следую за моим SQL-запросом.

SELECT * FROM table ORDER BY RAND() LIMIT 0,10; 

поэтому мои вопросы

  1. Мне нужно убедиться, что каждый раз пользователь посещает следующую страницу, результаты, которые они уже видели, не появлялись снова (исключают их в следующем запросе в эффективном режиме памяти, но все равно заказывают rand ())

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

  3. Я могу использовать семя в MYSQL, но я не уверен, как использовать это практически.

Случайное упорядочение в MySQL – это липкая проблема, поскольку они приходят. Раньше я обычно выбирал решение проблемы, когда это было возможно. Как правило, пользователь никогда не будет возвращаться к набору таких страниц более одного или двух раз. Таким образом, это дает вам возможность избежать всех различных отвратительных реализаций случайного порядка в пользу пары простых, но не вполне 100% случайных решений.

Решение 1

Выберите из нескольких существующих столбцов, которые уже проиндексированы для сортировки. Это может включать созданные, измененные временные метки или любой другой столбец, который вы можете отсортировать. Когда пользователь сначала приходит на сайт, они могут быть полезны в массиве, выбирайте один случайным образом, а затем произвольно выбирайте ASC или DESC .

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

Решение 2

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

UPDATE table SET rand_col = RAND ();

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

Используйте RAND (SEED) . Из документов: « Если указан постоянный целочисленный аргумент N, он используется как начальное значение». ( http://dev.mysql.com/doc/refman/5.0/en/mathematics-functions.html#function_rand ) ,

В приведенном выше примере порядок результата равен rand, но он всегда один и тот же. Вы просто меняете семя и получаете новый заказ.

 SELECT * FROM your_table ORDER BY RAND(351); 

Вы можете менять семя каждый раз, когда пользователь попадает на первую страницу результатов.

У вас есть несколько проблем! Я рекомендую вам шаг за шагом.

Первый выпуск: результаты, которые они уже видели, не появляются снова

  1. Каждый элемент возвращается, сохраняет его в одном массиве. (предполагая id индекса на примере)
  2. Когда пользователь перейдет на следующую страницу, перейдите к запросу NOT IN :

MySQL Query

 SELECT * FROM table WHERE id NOT IN (1, 14, 25, 645) ORDER BY RAND() LIMIT 0,10; 

Это делается для соответствия всем id , которые не являются 1, 14, 25 или 645.


Что касается проблемы производительности: в эффективном режиме памяти

 SELECT RAND( ) FROM table WHERE id NOT IN ( 1, 14, 25, 645 ) LIMIT 0 , 10 

Показаны строки 0 – 9 (всего 10 запросов, получено 0,0004 сек)

А ТАКЖЕ

 SELECT * FROM table WHERE id NOT IN ( 1, 14, 25, 645 ) ORDER BY RAND( ) LIMIT 0 , 10 

Показаны строки 0 – 9 (всего 10 запросов, получено 0,0609 сек)

Поэтому не используйте ORDER BY RAND (), предпочтительно используйте SELECT RAND ().

Сначала вы должны прекратить использование синтаксиса ORDER BY RAND. Это будет плохо для производительности в большом наборе строк.

Вам необходимо вручную определить ограничения LIMIT. Если вы все еще хотите использовать случайные результаты, и вы не хотите, чтобы пользователи видели одни и те же результаты на следующей странице, единственный способ – сохранить весь результат для этого сеанса поиска в базе данных и манипулировать этой информацией, когда пользователь перейдет на следующую страницу.

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

Я бы хотел, чтобы ваш PHP генерировал ваши случайные номера записей или строки для извлечения, передал их в ваш запрос и сохранил файл cookie на клиенте пользователя, указав, какие записи они уже видели.

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

Сочетание

  1. случайный порядок
  2. пагинация
  3. HTTP (без гражданства)

так же безобразно, как и приходит: 1. и 2. вместе нуждаются в какой-то «стойкой случайности», в то время как 3. делает это труднее достичь. В дополнение к этому 1. это не работа, оптимизированная для РСУБД.

Мое предложение зависит от того, насколько большой ваш набор данных:

Несколько строк (около <1K):

  • выберите все значения PK в первом запросе (первая страница)
  • перетасовывать их в PHP
  • хранить перетасованный список в сеансе
  • для каждого вызова страницы выберите данные в соответствии с сохраненными PK

Многие строки (10K +):

Это предполагает, что у вас есть уникальный ключ AUTO_INCREMENT с ID с управляемым количеством отверстий. При необходимости используйте скрипт amintenace (высокий коэффициент удаления)

  • Используйте функцию перетасовки, которая параметризуется, например, идентификатором сеанса, чтобы создать функцию rand_id(continuous_id)
  • Если вам нужно, например, записи от 100 000 до 100 009, вычислить $a=array(rand_id(100,000), rand_id(100,001), ... rand_id(100,009));
  • $a=implode(',',$a);
  • $sql="SELECT foo FROM bar WHERE ID IN($a) ORDER BY FIELD(ID,$a)";
  • Чтобы позаботиться о дырах в вашем идентификаторе, выберите несколько записей слишком много (и выбросьте exess), зациклив на слишком мало выбранных записей.