Показать 10 случайных строк из MySQL таблицы w / PHP - PullRequest
1 голос
/ 23 апреля 2020

Я провел тонну исследований по этому вопросу, но не могу найти ответ, который подходит для моей ситуации.

Я управляю веб-сайтом, где информация о 10000 продуктов хранится в MySQL база данных. Это число постоянно увеличивается и в итоге может получить до 20,30 или 40000 товаров.

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

Я не могу найти эффективный способ получения случайных строк из MySQL стол. Я часто упоминал о RAND (), но он очень медленный с чем-то более 100 строк. Я пробовал такие вещи, как генерация случайного числа на основе количества записей и извлечение по нему - но это не учитывает, если строка удалена, и тогда она не найдет результат. Это также означает, что мне придется выполнить инструкцию 10 раз для 10 случайных строк.

Я думал о сохранении всех строк в массиве, а затем вытягивал 10 случайных строк. Но также кажется неэффективным хранить минимум 10000 строк в массиве каждый раз, когда пользователь заходит на эту страницу.

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

Любой совет будет оценен: (

РЕДАКТИРОВАТЬ; SQL запрос, который я выполняю, который принимает 18 секунд с Рандом () - это:

SELECT Title,Price,Img,Seller,Positive,Negative,Neutral,Glowing,PD,STOCK,StoreItems.ItemURL,Currency,Verified, BTC, ETH, LTC, PayPal, Stripe, Stores.Verified FROM Stores JOIN StoreItems On Stores.StoreID = StoreItems.StoreID INNER JOIN Promotions ON StoreItems.ItemURL = Promotions.ItemID INNER JOIN Gateway ON StoreItems.ItemURL = Gateway.ItemURL WHERE Stores.Verified = 'true' ORDER BY RAND() LIMIT 5

Ответы [ 3 ]

1 голос
/ 23 апреля 2020

Определить супер медленный.

Я только что вытащил 50 случайных строк из таблицы 304 096 строк со временем выполнения 0,123327 секунд с помощью следующего запроса:

SELECT *
FROM `calendar`
ORDER BY RAND()
LIMIT 50;

Производительность, измеренная с помощью этого запрос:

SET profiling = 1;
SELECT *
FROM `calendar`
ORDER BY RAND()
LIMIT 50;
SELECT query_id, SUM(duration)
FROM information_schema.profiling
GROUP BY query_id
ORDER BY query_id
DESC LIMIT 3;
1 голос
/ 23 апреля 2020

Вы можете сгенерировать 10 псевдослучайных значений с помощью PHP rand и попытаться сопоставить идентификаторы

$r = [];
for ($i = 0; $i<10;$i++) {$r[] = rand(0, NUM_OF_PRODUCTS);}
$stmt = $conn->prepare("SELECT 1 FROM products WHERE id IN (?,?,?,?,?,?,?,?,?,?)");
$stmt->bind_param('iiiiiiiiii', $r[], $r[1], $r[2], $r[3], $r[4], $r[5], $r[6], $r[7], $r[8], $r[9]);
0 голосов
/ 24 апреля 2020

Я бы назначил им случайные числа с кроной, ежедневно или ежечасно, например от 1 до 10000, с одним запросом ОБНОВЛЕНИЯ.

UPDATE products SET static_random = FLOOR(RAND()*10000)

Поэтому вместо случайного назначения каждый раз «случайность» выполняется по расписанию. (Или просто используйте RAND () по умолчанию, который находится между 0 и 1). Затем на странице выберите случайное число с PHP ($ randomPosition}) в том же диапазоне, а затем вернитесь из MySQL что-то вроде:

SELECT * FROM products WHERE static_random > {$randomPosition} 
ORDER BY static_random ASC LIMIT 10

Таким образом, он выберет следующие 10 «случайных» предметов после случайного выбора позиции. Если при малой вероятности возврата менее 10, выберите другую случайную позицию.

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

Есть и другой способ рандомизировать назначенное случайное число стати c вместо крон. Может быть, случайный шанс 1 из 100 при посещении страницы или около того, назначьте им все случайные числа снова в одном запросе ОБНОВЛЕНИЯ (и определенно не отдельные запросы ОБНОВЛЕНИЯ). Или из 10 только что выбранных сгенерируйте новые случайные числа для всех c, так что небольшая партия каждый раз «перетасовывается» обратно в колоду в случайных местах.

Или вместо этого Вы всегда можете выбрать первые 10 элементов, упорядоченных по их случайному номеру c, и не использовать случайную позицию. Всегда начинайте с первой позиции. Это может помочь с разбиением на страницы, чтобы каждый раз получать одинаковые «случайные» наборы результатов.

Кроме того, для выбранных элементов вы можете генерировать новые случайные числа, возможно, в верхней части диапазона. Таким образом, они go приближаются к «концу стека» и с меньшей вероятностью будут выбраны снова, пока другие предметы не получат ход. Тем не менее, в какой-то момент вам, возможно, придется перетасовать их всех.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...